blob: 6c92a446f541b4dcd8f7699fe821ea48e54a2778 [file] [log] [blame]
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00001/*
msaboff@apple.com95894332014-01-29 19:18:54 +00002 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "JITOperations.h"
28
ossy@webkit.orgbeb0de42014-02-17 19:00:03 +000029#if ENABLE(JIT)
30
mark.lam@apple.com03944a02013-10-14 16:42:22 +000031#include "Arguments.h"
mark.lam@apple.com5d7e7082013-10-11 19:03:39 +000032#include "ArrayConstructor.h"
msaboff@apple.com4b6250f2013-10-15 18:33:04 +000033#include "DFGCompilationMode.h"
34#include "DFGDriver.h"
35#include "DFGOSREntry.h"
fpizlo@apple.com6fd929f2014-02-17 06:25:05 +000036#include "DFGThunks.h"
msaboff@apple.com4b6250f2013-10-15 18:33:04 +000037#include "DFGWorklist.h"
mark.lam@apple.com1b4227d2014-02-26 20:13:22 +000038#include "Debugger.h"
msaboff@apple.coma482c542013-10-04 18:20:40 +000039#include "Error.h"
msaboff@apple.com95894332014-01-29 19:18:54 +000040#include "ErrorHandlingScope.h"
fpizlo@apple.com8b5ff622014-07-22 18:27:17 +000041#include "ExceptionFuzz.h"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +000042#include "GetterSetter.h"
43#include "HostCallReturnValue.h"
msaboff@apple.com853b04f2013-10-17 01:23:56 +000044#include "JIT.h"
msaboff@apple.com4b6250f2013-10-15 18:33:04 +000045#include "JITToDFGDeferredCompilationCallback.h"
burg@cs.washington.edu1fc36ee2014-09-03 04:58:55 +000046#include "JSCInlines.h"
msaboff@apple.com2b95ada2013-10-09 13:29:00 +000047#include "JSGlobalObjectFunctions.h"
msaboff@apple.com4b6250f2013-10-15 18:33:04 +000048#include "JSNameScope.h"
fpizlo@apple.coma398a562014-08-06 21:32:55 +000049#include "JSPropertyNameEnumerator.h"
mark.lam@apple.com30721252013-11-21 05:29:42 +000050#include "JSStackInlines.h"
msaboff@apple.com4b6250f2013-10-15 18:33:04 +000051#include "JSWithScope.h"
burg@cs.washington.edu1fc36ee2014-09-03 04:58:55 +000052#include "LegacyProfiler.h"
mark.lam@apple.com5d7e7082013-10-11 19:03:39 +000053#include "ObjectConstructor.h"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +000054#include "Repatch.h"
msaboff@apple.com853b04f2013-10-17 01:23:56 +000055#include "RepatchBuffer.h"
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +000056#include "TestRunnerUtils.h"
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +000057#include "TypeProfilerLog.h"
commit-queue@webkit.orgdee92042014-04-09 21:41:40 +000058#include <wtf/InlineASM.h>
mark.lam@apple.com9df8b832013-09-26 20:27:14 +000059
60namespace JSC {
61
62extern "C" {
63
msaboff@apple.com2b95ada2013-10-09 13:29:00 +000064#if COMPILER(MSVC)
65void * _ReturnAddress(void);
66#pragma intrinsic(_ReturnAddress)
67
68#define OUR_RETURN_ADDRESS _ReturnAddress()
69#else
70#define OUR_RETURN_ADDRESS __builtin_return_address(0)
71#endif
72
73#if ENABLE(OPCODE_SAMPLING)
74#define CTI_SAMPLER vm->interpreter->sampler()
75#else
76#define CTI_SAMPLER 0
77#endif
78
79
msaboff@apple.com95894332014-01-29 19:18:54 +000080void JIT_OPERATION operationThrowStackOverflowError(ExecState* exec, CodeBlock* codeBlock)
msaboff@apple.com5ca16c42013-10-07 18:20:27 +000081{
82 // We pass in our own code block, because the callframe hasn't been populated.
83 VM* vm = codeBlock->vm();
msaboff@apple.com4d563e42014-08-16 01:45:40 +000084
msaboff@apple.com59979042014-08-20 00:36:13 +000085 VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
86 CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
msaboff@apple.com6f0b31a2013-12-04 16:40:17 +000087 if (!callerFrame)
88 callerFrame = exec;
89
msaboff@apple.com0576b242014-08-22 19:54:30 +000090 NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
msaboff@apple.com95894332014-01-29 19:18:54 +000091 ErrorHandlingScope errorScope(*vm);
92 vm->throwException(callerFrame, createStackOverflowError(callerFrame));
msaboff@apple.com5ca16c42013-10-07 18:20:27 +000093}
94
95int32_t JIT_OPERATION operationCallArityCheck(ExecState* exec)
96{
97 VM* vm = &exec->vm();
msaboff@apple.com59979042014-08-20 00:36:13 +000098 VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
99 CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
msaboff@apple.com5ca16c42013-10-07 18:20:27 +0000100
101 JSStack& stack = vm->interpreter->stack();
102
103 int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForCall);
msaboff@apple.com59979042014-08-20 00:36:13 +0000104 if (missingArgCount < 0) {
msaboff@apple.com0576b242014-08-22 19:54:30 +0000105 NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
msaboff@apple.com95894332014-01-29 19:18:54 +0000106 throwStackOverflowError(callerFrame);
msaboff@apple.com59979042014-08-20 00:36:13 +0000107 }
msaboff@apple.com5ca16c42013-10-07 18:20:27 +0000108
109 return missingArgCount;
110}
111
112int32_t JIT_OPERATION operationConstructArityCheck(ExecState* exec)
113{
114 VM* vm = &exec->vm();
msaboff@apple.com59979042014-08-20 00:36:13 +0000115 VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
116 CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
msaboff@apple.com5ca16c42013-10-07 18:20:27 +0000117
118 JSStack& stack = vm->interpreter->stack();
119
120 int32_t missingArgCount = CommonSlowPaths::arityCheckFor(exec, &stack, CodeForConstruct);
msaboff@apple.com59979042014-08-20 00:36:13 +0000121 if (missingArgCount < 0) {
msaboff@apple.com0576b242014-08-22 19:54:30 +0000122 NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
msaboff@apple.com95894332014-01-29 19:18:54 +0000123 throwStackOverflowError(callerFrame);
msaboff@apple.com59979042014-08-20 00:36:13 +0000124 }
msaboff@apple.com5ca16c42013-10-07 18:20:27 +0000125
126 return missingArgCount;
127}
128
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000129EncodedJSValue JIT_OPERATION operationGetById(ExecState* exec, StructureStubInfo*, EncodedJSValue base, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000130{
131 VM* vm = &exec->vm();
132 NativeCallFrameTracer tracer(vm, exec);
133
134 JSValue baseValue = JSValue::decode(base);
135 PropertySlot slot(baseValue);
136 Identifier ident(vm, uid);
137 return JSValue::encode(baseValue.get(exec, ident, slot));
138}
139
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000140EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000141{
142 VM* vm = &exec->vm();
143 NativeCallFrameTracer tracer(vm, exec);
144
145 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000146 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000147
148 JSValue baseValue = JSValue::decode(base);
149 PropertySlot slot(baseValue);
150 JSValue result = baseValue.get(exec, ident, slot);
151
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000152 if (accessType == static_cast<AccessType>(stubInfo->accessType))
153 buildGetByIDList(exec, baseValue, ident, slot, *stubInfo);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000154
155 return JSValue::encode(result);
156}
157
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000158EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000159{
160 VM* vm = &exec->vm();
161 NativeCallFrameTracer tracer(vm, exec);
oliver@apple.com20a9bf02013-10-04 20:35:24 +0000162 Identifier ident = uid->isEmptyUnique() ? Identifier::from(PrivateName(uid)) : Identifier(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000163 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000164
165 JSValue baseValue = JSValue::decode(base);
166 PropertySlot slot(baseValue);
167 JSValue result = baseValue.get(exec, ident, slot);
168
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000169 if (accessType == static_cast<AccessType>(stubInfo->accessType)) {
170 if (stubInfo->seen)
171 repatchGetByID(exec, baseValue, ident, slot, *stubInfo);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000172 else
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000173 stubInfo->seen = true;
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000174 }
175
176 return JSValue::encode(result);
177}
178
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000179EncodedJSValue JIT_OPERATION operationInOptimize(ExecState* exec, StructureStubInfo* stubInfo, JSCell* base, StringImpl* key)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000180{
181 VM* vm = &exec->vm();
182 NativeCallFrameTracer tracer(vm, exec);
183
184 if (!base->isObject()) {
185 vm->throwException(exec, createInvalidParameterError(exec, "in", base));
186 return JSValue::encode(jsUndefined());
187 }
188
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000189 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000190
191 Identifier ident(vm, key);
192 PropertySlot slot(base);
193 bool result = asObject(base)->getPropertySlot(exec, ident, slot);
194
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000195 RELEASE_ASSERT(accessType == stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000196
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000197 if (stubInfo->seen)
198 repatchIn(exec, base, ident, result, slot, *stubInfo);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000199 else
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000200 stubInfo->seen = true;
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000201
202 return JSValue::encode(jsBoolean(result));
203}
204
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000205EncodedJSValue JIT_OPERATION operationIn(ExecState* exec, StructureStubInfo*, JSCell* base, StringImpl* key)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000206{
207 VM* vm = &exec->vm();
208 NativeCallFrameTracer tracer(vm, exec);
209
210 if (!base->isObject()) {
211 vm->throwException(exec, createInvalidParameterError(exec, "in", base));
212 return JSValue::encode(jsUndefined());
213 }
214
215 Identifier ident(vm, key);
216 return JSValue::encode(jsBoolean(asObject(base)->hasProperty(exec, ident)));
217}
218
219EncodedJSValue JIT_OPERATION operationGenericIn(ExecState* exec, JSCell* base, EncodedJSValue key)
220{
221 VM* vm = &exec->vm();
222 NativeCallFrameTracer tracer(vm, exec);
223
224 return JSValue::encode(jsBoolean(CommonSlowPaths::opIn(exec, JSValue::decode(key), base)));
225}
226
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000227void JIT_OPERATION operationPutByIdStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000228{
229 VM* vm = &exec->vm();
230 NativeCallFrameTracer tracer(vm, exec);
231
232 Identifier ident(vm, uid);
oliver@apple.com68848412014-01-02 20:56:20 +0000233 PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000234 JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000235}
236
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000237void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000238{
239 VM* vm = &exec->vm();
240 NativeCallFrameTracer tracer(vm, exec);
241
242 Identifier ident(vm, uid);
oliver@apple.com68848412014-01-02 20:56:20 +0000243 PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000244 JSValue::decode(encodedBase).put(exec, ident, JSValue::decode(encodedValue), slot);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000245}
246
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000247void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000248{
249 VM* vm = &exec->vm();
250 NativeCallFrameTracer tracer(vm, exec);
251
252 Identifier ident(vm, uid);
oliver@apple.com68848412014-01-02 20:56:20 +0000253 PutPropertySlot slot(JSValue::decode(encodedBase), true, exec->codeBlock()->putByIdContext());
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000254 asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000255}
256
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000257void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000258{
259 VM* vm = &exec->vm();
260 NativeCallFrameTracer tracer(vm, exec);
261
262 Identifier ident(vm, uid);
oliver@apple.com68848412014-01-02 20:56:20 +0000263 PutPropertySlot slot(JSValue::decode(encodedBase), false, exec->codeBlock()->putByIdContext());
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000264 asObject(JSValue::decode(encodedBase))->putDirect(exec->vm(), ident, JSValue::decode(encodedValue), slot);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000265}
266
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000267void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000268{
269 VM* vm = &exec->vm();
270 NativeCallFrameTracer tracer(vm, exec);
271
272 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000273 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000274
275 JSValue value = JSValue::decode(encodedValue);
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000276 JSValue baseValue = JSValue::decode(encodedBase);
oliver@apple.com68848412014-01-02 20:56:20 +0000277 PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000278
279 baseValue.put(exec, ident, value, slot);
280
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000281 if (accessType != static_cast<AccessType>(stubInfo->accessType))
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000282 return;
283
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000284 if (stubInfo->seen)
285 repatchPutByID(exec, baseValue, ident, slot, *stubInfo, NotDirect);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000286 else
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000287 stubInfo->seen = true;
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000288}
289
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000290void JIT_OPERATION operationPutByIdNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000291{
292 VM* vm = &exec->vm();
293 NativeCallFrameTracer tracer(vm, exec);
294
295 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000296 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000297
298 JSValue value = JSValue::decode(encodedValue);
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000299 JSValue baseValue = JSValue::decode(encodedBase);
oliver@apple.com68848412014-01-02 20:56:20 +0000300 PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000301
302 baseValue.put(exec, ident, value, slot);
303
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000304 if (accessType != static_cast<AccessType>(stubInfo->accessType))
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000305 return;
306
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000307 if (stubInfo->seen)
308 repatchPutByID(exec, baseValue, ident, slot, *stubInfo, NotDirect);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000309 else
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000310 stubInfo->seen = true;
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000311}
312
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000313void JIT_OPERATION operationPutByIdDirectStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000314{
315 VM* vm = &exec->vm();
316 NativeCallFrameTracer tracer(vm, exec);
317
318 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000319 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000320
321 JSValue value = JSValue::decode(encodedValue);
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000322 JSObject* baseObject = asObject(JSValue::decode(encodedBase));
oliver@apple.com68848412014-01-02 20:56:20 +0000323 PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000324
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000325 baseObject->putDirect(exec->vm(), ident, value, slot);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000326
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000327 if (accessType != static_cast<AccessType>(stubInfo->accessType))
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000328 return;
329
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000330 if (stubInfo->seen)
331 repatchPutByID(exec, baseObject, ident, slot, *stubInfo, Direct);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000332 else
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000333 stubInfo->seen = true;
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000334}
335
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000336void JIT_OPERATION operationPutByIdDirectNonStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000337{
338 VM* vm = &exec->vm();
339 NativeCallFrameTracer tracer(vm, exec);
340
341 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000342 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000343
344 JSValue value = JSValue::decode(encodedValue);
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000345 JSObject* baseObject = asObject(JSValue::decode(encodedBase));
oliver@apple.com68848412014-01-02 20:56:20 +0000346 PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000347
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000348 baseObject->putDirect(exec->vm(), ident, value, slot);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000349
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000350 if (accessType != static_cast<AccessType>(stubInfo->accessType))
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000351 return;
352
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000353 if (stubInfo->seen)
354 repatchPutByID(exec, baseObject, ident, slot, *stubInfo, Direct);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000355 else
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000356 stubInfo->seen = true;
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000357}
358
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000359void JIT_OPERATION operationPutByIdStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000360{
361 VM* vm = &exec->vm();
362 NativeCallFrameTracer tracer(vm, exec);
363
364 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000365 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000366
367 JSValue value = JSValue::decode(encodedValue);
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000368 JSValue baseValue = JSValue::decode(encodedBase);
oliver@apple.com68848412014-01-02 20:56:20 +0000369 PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000370
371 baseValue.put(exec, ident, value, slot);
372
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000373 if (accessType != static_cast<AccessType>(stubInfo->accessType))
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000374 return;
375
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000376 buildPutByIdList(exec, baseValue, ident, slot, *stubInfo, NotDirect);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000377}
378
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000379void JIT_OPERATION operationPutByIdNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000380{
381 VM* vm = &exec->vm();
382 NativeCallFrameTracer tracer(vm, exec);
383
384 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000385 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000386
387 JSValue value = JSValue::decode(encodedValue);
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000388 JSValue baseValue = JSValue::decode(encodedBase);
oliver@apple.com68848412014-01-02 20:56:20 +0000389 PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000390
391 baseValue.put(exec, ident, value, slot);
392
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000393 if (accessType != static_cast<AccessType>(stubInfo->accessType))
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000394 return;
395
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000396 buildPutByIdList(exec, baseValue, ident, slot, *stubInfo, NotDirect);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000397}
398
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000399void JIT_OPERATION operationPutByIdDirectStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000400{
401 VM* vm = &exec->vm();
402 NativeCallFrameTracer tracer(vm, exec);
403
404 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000405 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000406
407 JSValue value = JSValue::decode(encodedValue);
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000408 JSObject* baseObject = asObject(JSValue::decode(encodedBase));
oliver@apple.com68848412014-01-02 20:56:20 +0000409 PutPropertySlot slot(baseObject, true, exec->codeBlock()->putByIdContext());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000410
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000411 baseObject->putDirect(exec->vm(), ident, value, slot);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000412
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000413 if (accessType != static_cast<AccessType>(stubInfo->accessType))
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000414 return;
415
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000416 buildPutByIdList(exec, baseObject, ident, slot, *stubInfo, Direct);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000417}
418
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000419void JIT_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl* uid)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000420{
421 VM* vm = &exec->vm();
422 NativeCallFrameTracer tracer(vm, exec);
423
424 Identifier ident(vm, uid);
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000425 AccessType accessType = static_cast<AccessType>(stubInfo->accessType);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000426
427 JSValue value = JSValue::decode(encodedValue);
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000428 JSObject* baseObject = asObject(JSValue::decode(encodedBase));
oliver@apple.com68848412014-01-02 20:56:20 +0000429 PutPropertySlot slot(baseObject, false, exec->codeBlock()->putByIdContext());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000430
fpizlo@apple.comd97d7572013-10-14 18:39:45 +0000431 baseObject ->putDirect(exec->vm(), ident, value, slot);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000432
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000433 if (accessType != static_cast<AccessType>(stubInfo->accessType))
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000434 return;
435
fpizlo@apple.comd49bfe82013-10-19 02:20:14 +0000436 buildPutByIdList(exec, baseObject, ident, slot, *stubInfo, Direct);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000437}
438
439void JIT_OPERATION operationReallocateStorageAndFinishPut(ExecState* exec, JSObject* base, Structure* structure, PropertyOffset offset, EncodedJSValue value)
440{
441 VM& vm = exec->vm();
442 NativeCallFrameTracer tracer(&vm, exec);
443
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000444 ASSERT(structure->outOfLineCapacity() > base->structure(vm)->outOfLineCapacity());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000445 ASSERT(!vm.heap.storageAllocator().fastPathShouldSucceed(structure->outOfLineCapacity() * sizeof(JSValue)));
446 base->setStructureAndReallocateStorageIfNecessary(vm, structure);
447 base->putDirect(vm, offset, JSValue::decode(value));
448}
449
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000450static void putByVal(CallFrame* callFrame, JSValue baseValue, JSValue subscript, JSValue value)
451{
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000452 VM& vm = callFrame->vm();
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000453 if (LIKELY(subscript.isUInt32())) {
454 uint32_t i = subscript.asUInt32();
455 if (baseValue.isObject()) {
456 JSObject* object = asObject(baseValue);
457 if (object->canSetIndexQuickly(i))
458 object->setIndexQuickly(callFrame->vm(), i, value);
459 else
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000460 object->methodTable(vm)->putByIndex(object, callFrame, i, value, callFrame->codeBlock()->isStrictMode());
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000461 } else
462 baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode());
463 } else if (isName(subscript)) {
oliver@apple.com68848412014-01-02 20:56:20 +0000464 PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000465 baseValue.put(callFrame, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
466 } else {
akling@apple.com83343ba2014-05-05 18:08:25 +0000467 Identifier property = subscript.toString(callFrame)->toIdentifier(callFrame);
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000468 if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
oliver@apple.com68848412014-01-02 20:56:20 +0000469 PutPropertySlot slot(baseValue, callFrame->codeBlock()->isStrictMode());
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000470 baseValue.put(callFrame, property, value, slot);
471 }
472 }
473}
474
oliver@apple.come050d642013-10-19 00:09:28 +0000475static void directPutByVal(CallFrame* callFrame, JSObject* baseObject, JSValue subscript, JSValue value)
476{
477 if (LIKELY(subscript.isUInt32())) {
478 uint32_t i = subscript.asUInt32();
479 baseObject->putDirectIndex(callFrame, i, value);
480 } else if (isName(subscript)) {
oliver@apple.com68848412014-01-02 20:56:20 +0000481 PutPropertySlot slot(baseObject, callFrame->codeBlock()->isStrictMode());
oliver@apple.come050d642013-10-19 00:09:28 +0000482 baseObject->putDirect(callFrame->vm(), jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot);
483 } else {
akling@apple.com667966a2014-08-28 21:38:18 +0000484 Identifier property = subscript.toString(callFrame)->toIdentifier(callFrame);
oliver@apple.come050d642013-10-19 00:09:28 +0000485 if (!callFrame->vm().exception()) { // Don't put to an object if toString threw an exception.
oliver@apple.com68848412014-01-02 20:56:20 +0000486 PutPropertySlot slot(baseObject, callFrame->codeBlock()->isStrictMode());
oliver@apple.come050d642013-10-19 00:09:28 +0000487 baseObject->putDirect(callFrame->vm(), property, value, slot);
488 }
489 }
490}
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000491void JIT_OPERATION operationPutByVal(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
492{
493 VM& vm = exec->vm();
494 NativeCallFrameTracer tracer(&vm, exec);
495
496 JSValue baseValue = JSValue::decode(encodedBaseValue);
497 JSValue subscript = JSValue::decode(encodedSubscript);
498 JSValue value = JSValue::decode(encodedValue);
499
500 if (baseValue.isObject() && subscript.isInt32()) {
501 // See if it's worth optimizing at all.
502 JSObject* object = asObject(baseValue);
503 bool didOptimize = false;
504
505 unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
506 ASSERT(bytecodeOffset);
507 ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
508 ASSERT(!byValInfo.stubRoutine);
509
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000510 if (hasOptimizableIndexing(object->structure(vm))) {
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000511 // Attempt to optimize.
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000512 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000513 if (arrayMode != byValInfo.arrayMode) {
514 JIT::compilePutByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
515 didOptimize = true;
516 }
517 }
518
519 if (!didOptimize) {
520 // If we take slow path more than 10 times without patching then make sure we
521 // never make that mistake again. Or, if we failed to patch and we have some object
522 // that intercepts indexed get, then don't even wait until 10 times. For cases
523 // where we see non-index-intercepting objects, this gives 10 iterations worth of
524 // opportunity for us to observe that the get_by_val may be polymorphic.
525 if (++byValInfo.slowPathCount >= 10
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000526 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000527 // Don't ever try to optimize.
528 RepatchBuffer repatchBuffer(exec->codeBlock());
529 repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationPutByValGeneric));
530 }
531 }
532 }
533
534 putByVal(exec, baseValue, subscript, value);
535}
536
oliver@apple.come050d642013-10-19 00:09:28 +0000537void JIT_OPERATION operationDirectPutByVal(ExecState* callFrame, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
538{
539 VM& vm = callFrame->vm();
540 NativeCallFrameTracer tracer(&vm, callFrame);
541
542 JSValue baseValue = JSValue::decode(encodedBaseValue);
543 JSValue subscript = JSValue::decode(encodedSubscript);
544 JSValue value = JSValue::decode(encodedValue);
545 RELEASE_ASSERT(baseValue.isObject());
546 JSObject* object = asObject(baseValue);
547 if (subscript.isInt32()) {
548 // See if it's worth optimizing at all.
549 bool didOptimize = false;
550
551 unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
552 ASSERT(bytecodeOffset);
553 ByValInfo& byValInfo = callFrame->codeBlock()->getByValInfo(bytecodeOffset - 1);
554 ASSERT(!byValInfo.stubRoutine);
555
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000556 if (hasOptimizableIndexing(object->structure(vm))) {
oliver@apple.come050d642013-10-19 00:09:28 +0000557 // Attempt to optimize.
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000558 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
oliver@apple.come050d642013-10-19 00:09:28 +0000559 if (arrayMode != byValInfo.arrayMode) {
560 JIT::compileDirectPutByVal(&vm, callFrame->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
561 didOptimize = true;
562 }
563 }
564
565 if (!didOptimize) {
566 // If we take slow path more than 10 times without patching then make sure we
567 // never make that mistake again. Or, if we failed to patch and we have some object
568 // that intercepts indexed get, then don't even wait until 10 times. For cases
569 // where we see non-index-intercepting objects, this gives 10 iterations worth of
570 // opportunity for us to observe that the get_by_val may be polymorphic.
571 if (++byValInfo.slowPathCount >= 10
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +0000572 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
oliver@apple.come050d642013-10-19 00:09:28 +0000573 // Don't ever try to optimize.
574 RepatchBuffer repatchBuffer(callFrame->codeBlock());
575 repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationDirectPutByValGeneric));
576 }
577 }
578 }
579 directPutByVal(callFrame, object, subscript, value);
580}
581
msaboff@apple.com853b04f2013-10-17 01:23:56 +0000582void JIT_OPERATION operationPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
583{
584 VM& vm = exec->vm();
585 NativeCallFrameTracer tracer(&vm, exec);
586
587 JSValue baseValue = JSValue::decode(encodedBaseValue);
588 JSValue subscript = JSValue::decode(encodedSubscript);
589 JSValue value = JSValue::decode(encodedValue);
590
591 putByVal(exec, baseValue, subscript, value);
592}
593
oliver@apple.come050d642013-10-19 00:09:28 +0000594
595void JIT_OPERATION operationDirectPutByValGeneric(ExecState* exec, EncodedJSValue encodedBaseValue, EncodedJSValue encodedSubscript, EncodedJSValue encodedValue)
596{
597 VM& vm = exec->vm();
598 NativeCallFrameTracer tracer(&vm, exec);
599
600 JSValue baseValue = JSValue::decode(encodedBaseValue);
601 JSValue subscript = JSValue::decode(encodedSubscript);
602 JSValue value = JSValue::decode(encodedValue);
603 RELEASE_ASSERT(baseValue.isObject());
604 directPutByVal(exec, asObject(baseValue), subscript, value);
605}
606
msaboff@apple.com95894332014-01-29 19:18:54 +0000607EncodedJSValue JIT_OPERATION operationCallEval(ExecState* exec, ExecState* execCallee)
msaboff@apple.com2b95ada2013-10-09 13:29:00 +0000608{
msaboff@apple.com95894332014-01-29 19:18:54 +0000609 ASSERT(exec->codeBlock()->codeType() != FunctionCode
mark.lam@apple.com65a636f2014-02-01 01:24:39 +0000610 || !exec->codeBlock()->needsActivation()
611 || exec->hasActivation());
msaboff@apple.com2b95ada2013-10-09 13:29:00 +0000612
msaboff@apple.com95894332014-01-29 19:18:54 +0000613 execCallee->setScope(exec->scope());
msaboff@apple.com2b95ada2013-10-09 13:29:00 +0000614 execCallee->setCodeBlock(0);
615
616 if (!isHostFunction(execCallee->calleeAsValue(), globalFuncEval))
617 return JSValue::encode(JSValue());
618
619 VM* vm = &execCallee->vm();
620 JSValue result = eval(execCallee);
621 if (vm->exception())
622 return EncodedJSValue();
623
624 return JSValue::encode(result);
625}
626
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000627static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializationKind kind)
628{
629 ExecState* exec = execCallee->callerFrame();
630 VM* vm = &exec->vm();
631
632 execCallee->setScope(exec->scope());
633 execCallee->setCodeBlock(0);
634
635 if (kind == CodeForCall) {
636 CallData callData;
637 CallType callType = getCallData(callee, callData);
638
639 ASSERT(callType != CallTypeJS);
640
641 if (callType == CallTypeHost) {
642 NativeCallFrameTracer tracer(vm, execCallee);
643 execCallee->setCallee(asObject(callee));
644 vm->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee));
645 if (vm->exception())
646 return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
647
648 return reinterpret_cast<void*>(getHostCallReturnValue);
649 }
650
651 ASSERT(callType == CallTypeNone);
652 exec->vm().throwException(exec, createNotAFunctionError(exec, callee));
653 return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
654 }
655
656 ASSERT(kind == CodeForConstruct);
657
658 ConstructData constructData;
659 ConstructType constructType = getConstructData(callee, constructData);
660
661 ASSERT(constructType != ConstructTypeJS);
662
663 if (constructType == ConstructTypeHost) {
664 NativeCallFrameTracer tracer(vm, execCallee);
665 execCallee->setCallee(asObject(callee));
666 vm->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee));
667 if (vm->exception())
668 return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
669
670 return reinterpret_cast<void*>(getHostCallReturnValue);
671 }
672
673 ASSERT(constructType == ConstructTypeNone);
674 exec->vm().throwException(exec, createNotAConstructorError(exec, callee));
675 return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
676}
677
msaboff@apple.com95894332014-01-29 19:18:54 +0000678inline char* linkFor(
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000679 ExecState* execCallee, CallLinkInfo* callLinkInfo, CodeSpecializationKind kind,
680 RegisterPreservationMode registers)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000681{
682 ExecState* exec = execCallee->callerFrame();
683 VM* vm = &exec->vm();
684 NativeCallFrameTracer tracer(vm, exec);
685
686 JSValue calleeAsValue = execCallee->calleeAsValue();
687 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue);
688 if (!calleeAsFunctionCell)
689 return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
690
691 JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
ggaren@apple.com7d92d072014-02-03 20:39:38 +0000692 JSScope* scope = callee->scopeUnchecked();
693 execCallee->setScope(scope);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000694 ExecutableBase* executable = callee->executable();
695
696 MacroAssemblerCodePtr codePtr;
697 CodeBlock* codeBlock = 0;
698 if (executable->isHostFunction())
msaboff@apple.com95894332014-01-29 19:18:54 +0000699 codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, registers);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000700 else {
701 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
ggaren@apple.com7d92d072014-02-03 20:39:38 +0000702 JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, &scope, kind);
703 execCallee->setScope(scope);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000704 if (error) {
msaboff@apple.com95894332014-01-29 19:18:54 +0000705 throwStackOverflowError(exec);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000706 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
707 }
708 codeBlock = functionExecutable->codeBlockFor(kind);
msaboff@apple.com95894332014-01-29 19:18:54 +0000709 ArityCheckMode arity;
oliver@apple.com177c2b92014-03-28 01:10:25 +0000710 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType == CallLinkInfo::CallVarargs || callLinkInfo->callType == CallLinkInfo::ConstructVarargs)
msaboff@apple.com95894332014-01-29 19:18:54 +0000711 arity = MustCheckArity;
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000712 else
msaboff@apple.com95894332014-01-29 19:18:54 +0000713 arity = ArityCheckNotRequired;
714 codePtr = functionExecutable->entrypointFor(*vm, kind, arity, registers);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000715 }
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000716 if (!callLinkInfo->seenOnce())
717 callLinkInfo->setSeen();
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000718 else
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000719 linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr, kind, registers);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000720 return reinterpret_cast<char*>(codePtr.executableAddress());
721}
722
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000723char* JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000724{
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000725 return linkFor(execCallee, callLinkInfo, CodeForCall, RegisterPreservationNotRequired);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000726}
727
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000728char* JIT_OPERATION operationLinkConstruct(ExecState* execCallee, CallLinkInfo* callLinkInfo)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000729{
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000730 return linkFor(execCallee, callLinkInfo, CodeForConstruct, RegisterPreservationNotRequired);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000731}
732
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000733char* JIT_OPERATION operationLinkCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
msaboff@apple.com95894332014-01-29 19:18:54 +0000734{
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000735 return linkFor(execCallee, callLinkInfo, CodeForCall, MustPreserveRegisters);
msaboff@apple.com95894332014-01-29 19:18:54 +0000736}
737
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000738char* JIT_OPERATION operationLinkConstructThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
msaboff@apple.com95894332014-01-29 19:18:54 +0000739{
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000740 return linkFor(execCallee, callLinkInfo, CodeForConstruct, MustPreserveRegisters);
msaboff@apple.com95894332014-01-29 19:18:54 +0000741}
742
743inline char* virtualForWithFunction(
744 ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers,
745 JSCell*& calleeAsFunctionCell)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000746{
747 ExecState* exec = execCallee->callerFrame();
748 VM* vm = &exec->vm();
749 NativeCallFrameTracer tracer(vm, exec);
750
751 JSValue calleeAsValue = execCallee->calleeAsValue();
752 calleeAsFunctionCell = getJSFunction(calleeAsValue);
753 if (UNLIKELY(!calleeAsFunctionCell))
754 return reinterpret_cast<char*>(handleHostCall(execCallee, calleeAsValue, kind));
755
756 JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell);
ggaren@apple.com7d92d072014-02-03 20:39:38 +0000757 JSScope* scope = function->scopeUnchecked();
758 execCallee->setScope(scope);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000759 ExecutableBase* executable = function->executable();
760 if (UNLIKELY(!executable->hasJITCodeFor(kind))) {
761 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
ggaren@apple.com7d92d072014-02-03 20:39:38 +0000762 JSObject* error = functionExecutable->prepareForExecution(execCallee, function, &scope, kind);
763 execCallee->setScope(scope);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000764 if (error) {
mark.lam@apple.comeae88c92014-02-21 06:07:37 +0000765 exec->vm().throwException(exec, error);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000766 return reinterpret_cast<char*>(vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress());
767 }
768 }
msaboff@apple.com95894332014-01-29 19:18:54 +0000769 return reinterpret_cast<char*>(executable->entrypointFor(
770 *vm, kind, MustCheckArity, registers).executableAddress());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000771}
772
msaboff@apple.com95894332014-01-29 19:18:54 +0000773inline char* virtualFor(
774 ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000775{
776 JSCell* calleeAsFunctionCellIgnored;
msaboff@apple.com95894332014-01-29 19:18:54 +0000777 return virtualForWithFunction(execCallee, kind, registers, calleeAsFunctionCellIgnored);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000778}
779
msaboff@apple.com95894332014-01-29 19:18:54 +0000780static bool attemptToOptimizeClosureCall(
781 ExecState* execCallee, RegisterPreservationMode registers, JSCell* calleeAsFunctionCell,
782 CallLinkInfo& callLinkInfo)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000783{
784 if (!calleeAsFunctionCell)
785 return false;
786
787 JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell);
788 JSFunction* oldCallee = callLinkInfo.callee.get();
789
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000790 if (!oldCallee || oldCallee->executable() != callee->executable())
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000791 return false;
792
793 ASSERT(callee->executable()->hasJITCodeForCall());
msaboff@apple.com95894332014-01-29 19:18:54 +0000794 MacroAssemblerCodePtr codePtr =
795 callee->executable()->generatedJITCodeForCall()->addressForCall(
796 *execCallee->callerFrame()->codeBlock()->vm(), callee->executable(),
797 ArityCheckNotRequired, registers);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000798
799 CodeBlock* codeBlock;
800 if (callee->executable()->isHostFunction())
801 codeBlock = 0;
802 else {
803 codeBlock = jsCast<FunctionExecutable*>(callee->executable())->codeBlockForCall();
oliver@apple.com177c2b92014-03-28 01:10:25 +0000804 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType == CallLinkInfo::CallVarargs || callLinkInfo.callType == CallLinkInfo::ConstructVarargs)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000805 return false;
806 }
807
808 linkClosureCall(
fpizlo@apple.coma398a562014-08-06 21:32:55 +0000809 execCallee, callLinkInfo, codeBlock, callee->executable(), codePtr, registers);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000810
811 return true;
812}
813
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000814char* JIT_OPERATION operationLinkClosureCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000815{
816 JSCell* calleeAsFunctionCell;
msaboff@apple.com95894332014-01-29 19:18:54 +0000817 char* result = virtualForWithFunction(execCallee, CodeForCall, RegisterPreservationNotRequired, calleeAsFunctionCell);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000818
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000819 if (!attemptToOptimizeClosureCall(execCallee, RegisterPreservationNotRequired, calleeAsFunctionCell, *callLinkInfo))
820 linkSlowFor(execCallee, *callLinkInfo, CodeForCall, RegisterPreservationNotRequired);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000821
822 return result;
823}
824
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000825char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo*)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000826{
msaboff@apple.com95894332014-01-29 19:18:54 +0000827 return virtualFor(execCallee, CodeForCall, RegisterPreservationNotRequired);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000828}
829
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000830char* JIT_OPERATION operationVirtualConstruct(ExecState* execCallee, CallLinkInfo*)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000831{
msaboff@apple.com95894332014-01-29 19:18:54 +0000832 return virtualFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +0000833}
834
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000835char* JIT_OPERATION operationLinkClosureCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
msaboff@apple.com95894332014-01-29 19:18:54 +0000836{
837 JSCell* calleeAsFunctionCell;
838 char* result = virtualForWithFunction(execCallee, CodeForCall, MustPreserveRegisters, calleeAsFunctionCell);
msaboff@apple.com95894332014-01-29 19:18:54 +0000839
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000840 if (!attemptToOptimizeClosureCall(execCallee, MustPreserveRegisters, calleeAsFunctionCell, *callLinkInfo))
841 linkSlowFor(execCallee, *callLinkInfo, CodeForCall, MustPreserveRegisters);
msaboff@apple.com95894332014-01-29 19:18:54 +0000842
843 return result;
844}
845
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000846char* JIT_OPERATION operationVirtualCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo*)
msaboff@apple.com95894332014-01-29 19:18:54 +0000847{
848 return virtualFor(execCallee, CodeForCall, MustPreserveRegisters);
849}
850
fpizlo@apple.comba262b22014-03-23 04:34:38 +0000851char* JIT_OPERATION operationVirtualConstructThatPreservesRegs(ExecState* execCallee, CallLinkInfo*)
msaboff@apple.com95894332014-01-29 19:18:54 +0000852{
853 return virtualFor(execCallee, CodeForConstruct, MustPreserveRegisters);
854}
msaboff@apple.comc8dd3f72013-10-10 23:10:40 +0000855
856size_t JIT_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
857{
858 VM* vm = &exec->vm();
859 NativeCallFrameTracer tracer(vm, exec);
860
861 return jsLess<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
862}
863
864size_t JIT_OPERATION operationCompareLessEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
865{
866 VM* vm = &exec->vm();
867 NativeCallFrameTracer tracer(vm, exec);
868
869 return jsLessEq<true>(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
870}
871
872size_t JIT_OPERATION operationCompareGreater(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
873{
874 VM* vm = &exec->vm();
875 NativeCallFrameTracer tracer(vm, exec);
876
877 return jsLess<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
878}
879
880size_t JIT_OPERATION operationCompareGreaterEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
881{
882 VM* vm = &exec->vm();
883 NativeCallFrameTracer tracer(vm, exec);
884
885 return jsLessEq<false>(exec, JSValue::decode(encodedOp2), JSValue::decode(encodedOp1));
886}
887
888size_t JIT_OPERATION operationConvertJSValueToBoolean(ExecState* exec, EncodedJSValue encodedOp)
889{
890 VM* vm = &exec->vm();
891 NativeCallFrameTracer tracer(vm, exec);
892
893 return JSValue::decode(encodedOp).toBoolean(exec);
894}
895
896size_t JIT_OPERATION operationCompareEq(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
897{
898 VM* vm = &exec->vm();
899 NativeCallFrameTracer tracer(vm, exec);
900
901 return JSValue::equalSlowCaseInline(exec, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2));
902}
903
904#if USE(JSVALUE64)
905EncodedJSValue JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
906#else
907size_t JIT_OPERATION operationCompareStringEq(ExecState* exec, JSCell* left, JSCell* right)
908#endif
909{
910 VM* vm = &exec->vm();
911 NativeCallFrameTracer tracer(vm, exec);
912
benjamin@webkit.orgb3b77302014-04-14 08:46:27 +0000913 bool result = WTF::equal(*asString(left)->value(exec).impl(), *asString(right)->value(exec).impl());
msaboff@apple.comc8dd3f72013-10-10 23:10:40 +0000914#if USE(JSVALUE64)
915 return JSValue::encode(jsBoolean(result));
916#else
917 return result;
918#endif
919}
920
921size_t JIT_OPERATION operationHasProperty(ExecState* exec, JSObject* base, JSString* property)
922{
akling@apple.com667966a2014-08-28 21:38:18 +0000923 int result = base->hasProperty(exec, property->toIdentifier(exec));
msaboff@apple.comc8dd3f72013-10-10 23:10:40 +0000924 return result;
925}
926
927
mark.lam@apple.com5d7e7082013-10-11 19:03:39 +0000928EncodedJSValue JIT_OPERATION operationNewArrayWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
929{
930 VM* vm = &exec->vm();
931 NativeCallFrameTracer tracer(vm, exec);
932 return JSValue::encode(constructArrayNegativeIndexed(exec, profile, values, size));
933}
934
935EncodedJSValue JIT_OPERATION operationNewArrayBufferWithProfile(ExecState* exec, ArrayAllocationProfile* profile, const JSValue* values, int size)
936{
937 VM* vm = &exec->vm();
938 NativeCallFrameTracer tracer(vm, exec);
939 return JSValue::encode(constructArray(exec, profile, values, size));
940}
941
942EncodedJSValue JIT_OPERATION operationNewArrayWithSizeAndProfile(ExecState* exec, ArrayAllocationProfile* profile, EncodedJSValue size)
943{
944 VM* vm = &exec->vm();
945 NativeCallFrameTracer tracer(vm, exec);
946 JSValue sizeValue = JSValue::decode(size);
947 return JSValue::encode(constructArrayWithSizeQuirk(exec, profile, exec->lexicalGlobalObject(), sizeValue));
948}
949
msaboff@apple.comea77cd02014-11-14 01:07:48 +0000950EncodedJSValue JIT_OPERATION operationNewFunction(ExecState* exec, JSScope* scope, JSCell* functionExecutable)
mark.lam@apple.com5d7e7082013-10-11 19:03:39 +0000951{
952 ASSERT(functionExecutable->inherits(FunctionExecutable::info()));
953 VM& vm = exec->vm();
954 NativeCallFrameTracer tracer(&vm, exec);
msaboff@apple.comea77cd02014-11-14 01:07:48 +0000955 return JSValue::encode(JSFunction::create(vm, static_cast<FunctionExecutable*>(functionExecutable), scope));
mark.lam@apple.com5d7e7082013-10-11 19:03:39 +0000956}
957
958JSCell* JIT_OPERATION operationNewObject(ExecState* exec, Structure* structure)
959{
960 VM* vm = &exec->vm();
961 NativeCallFrameTracer tracer(vm, exec);
962
963 return constructEmptyObject(exec, structure);
964}
965
msaboff@apple.coma482c542013-10-04 18:20:40 +0000966EncodedJSValue JIT_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr)
967{
968 VM& vm = exec->vm();
969 NativeCallFrameTracer tracer(&vm, exec);
970 RegExp* regexp = static_cast<RegExp*>(regexpPtr);
971 if (!regexp->isValid()) {
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +0000972 vm.throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
msaboff@apple.coma482c542013-10-04 18:20:40 +0000973 return JSValue::encode(jsUndefined());
974 }
975
976 return JSValue::encode(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regexp));
977}
978
msaboff@apple.com4b6250f2013-10-15 18:33:04 +0000979void JIT_OPERATION operationHandleWatchdogTimer(ExecState* exec)
980{
981 VM& vm = exec->vm();
982 NativeCallFrameTracer tracer(&vm, exec);
983
mhahnenberg@apple.comcaa485e2014-05-20 22:55:49 +0000984 if (UNLIKELY(vm.watchdog && vm.watchdog->didFire(exec)))
msaboff@apple.com4b6250f2013-10-15 18:33:04 +0000985 vm.throwException(exec, createTerminatedExecutionException(&vm));
986}
987
988void JIT_OPERATION operationThrowStaticError(ExecState* exec, EncodedJSValue encodedValue, int32_t referenceErrorFlag)
989{
990 VM& vm = exec->vm();
991 NativeCallFrameTracer tracer(&vm, exec);
992
993 String message = errorDescriptionForValue(exec, JSValue::decode(encodedValue))->value(exec);
994 if (referenceErrorFlag)
995 vm.throwException(exec, createReferenceError(exec, message));
996 else
997 vm.throwException(exec, createTypeError(exec, message));
998}
999
1000void JIT_OPERATION operationDebug(ExecState* exec, int32_t debugHookID)
1001{
1002 VM& vm = exec->vm();
1003 NativeCallFrameTracer tracer(&vm, exec);
1004
1005 vm.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID));
1006}
1007
1008#if ENABLE(DFG_JIT)
mark.lam@apple.com1b4227d2014-02-26 20:13:22 +00001009static void updateAllPredictionsAndOptimizeAfterWarmUp(CodeBlock* codeBlock)
1010{
1011 codeBlock->updateAllPredictions();
1012 codeBlock->optimizeAfterWarmUp();
1013}
1014
msaboff@apple.com95894332014-01-29 19:18:54 +00001015SlowPathReturnType JIT_OPERATION operationOptimize(ExecState* exec, int32_t bytecodeIndex)
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001016{
1017 VM& vm = exec->vm();
1018 NativeCallFrameTracer tracer(&vm, exec);
1019
mark.lam@apple.comb5c90a02014-05-20 02:03:47 +00001020 // Defer GC for a while so that it doesn't run between when we enter into this
1021 // slow path and when we figure out the state of our code block. This prevents
1022 // a number of awkward reentrancy scenarios, including:
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001023 //
1024 // - The optimized version of our code block being jettisoned by GC right after
mark.lam@apple.comb5c90a02014-05-20 02:03:47 +00001025 // we concluded that we wanted to use it, but have not planted it into the JS
1026 // stack yet.
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001027 //
1028 // - An optimized version of our code block being installed just as we decided
1029 // that it wasn't ready yet.
1030 //
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001031 // Note that jettisoning won't happen if we already initiated OSR, because in
1032 // that case we would have already planted the optimized code block into the JS
1033 // stack.
mark.lam@apple.comb5c90a02014-05-20 02:03:47 +00001034 DeferGCForAWhile deferGC(vm.heap);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001035
1036 CodeBlock* codeBlock = exec->codeBlock();
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +00001037
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001038 if (bytecodeIndex) {
1039 // If we're attempting to OSR from a loop, assume that this should be
1040 // separately optimized.
1041 codeBlock->m_shouldAlwaysBeInlined = false;
1042 }
1043
1044 if (Options::verboseOSR()) {
1045 dataLog(
1046 *codeBlock, ": Entered optimize with bytecodeIndex = ", bytecodeIndex,
1047 ", executeCounter = ", codeBlock->jitExecuteCounter(),
1048 ", optimizationDelayCounter = ", codeBlock->reoptimizationRetryCounter(),
1049 ", exitCounter = ");
1050 if (codeBlock->hasOptimizedReplacement())
1051 dataLog(codeBlock->replacement()->osrExitCounter());
1052 else
1053 dataLog("N/A");
1054 dataLog("\n");
1055 }
1056
1057 if (!codeBlock->checkIfOptimizationThresholdReached()) {
1058 codeBlock->updateAllPredictions();
1059 if (Options::verboseOSR())
1060 dataLog("Choosing not to optimize ", *codeBlock, " yet, because the threshold hasn't been reached.\n");
msaboff@apple.com95894332014-01-29 19:18:54 +00001061 return encodeResult(0, 0);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001062 }
1063
mark.lam@apple.com1b4227d2014-02-26 20:13:22 +00001064 if (vm.enabledProfiler()) {
1065 updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1066 return encodeResult(0, 0);
1067 }
1068
1069 Debugger* debugger = codeBlock->globalObject()->debugger();
1070 if (debugger && (debugger->isStepping() || codeBlock->baselineAlternative()->hasDebuggerRequests())) {
1071 updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
1072 return encodeResult(0, 0);
1073 }
1074
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001075 if (codeBlock->m_shouldAlwaysBeInlined) {
mark.lam@apple.com1b4227d2014-02-26 20:13:22 +00001076 updateAllPredictionsAndOptimizeAfterWarmUp(codeBlock);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001077 if (Options::verboseOSR())
1078 dataLog("Choosing not to optimize ", *codeBlock, " yet, because m_shouldAlwaysBeInlined == true.\n");
msaboff@apple.com95894332014-01-29 19:18:54 +00001079 return encodeResult(0, 0);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001080 }
1081
1082 // We cannot be in the process of asynchronous compilation and also have an optimized
1083 // replacement.
msaboff@apple.com95894332014-01-29 19:18:54 +00001084 DFG::Worklist* worklist = DFG::existingGlobalDFGWorklistOrNull();
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001085 ASSERT(
msaboff@apple.com95894332014-01-29 19:18:54 +00001086 !worklist
1087 || !(worklist->compilationState(DFG::CompilationKey(codeBlock, DFG::DFGMode)) != DFG::Worklist::NotKnown
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001088 && codeBlock->hasOptimizedReplacement()));
1089
1090 DFG::Worklist::State worklistState;
msaboff@apple.com95894332014-01-29 19:18:54 +00001091 if (worklist) {
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001092 // The call to DFG::Worklist::completeAllReadyPlansForVM() will complete all ready
1093 // (i.e. compiled) code blocks. But if it completes ours, we also need to know
1094 // what the result was so that we don't plow ahead and attempt OSR or immediate
1095 // reoptimization. This will have already also set the appropriate JIT execution
1096 // count threshold depending on what happened, so if the compilation was anything
1097 // but successful we just want to return early. See the case for worklistState ==
1098 // DFG::Worklist::Compiled, below.
1099
1100 // Note that we could have alternatively just called Worklist::compilationState()
1101 // here, and if it returned Compiled, we could have then called
1102 // completeAndScheduleOSR() below. But that would have meant that it could take
1103 // longer for code blocks to be completed: they would only complete when *their*
1104 // execution count trigger fired; but that could take a while since the firing is
1105 // racy. It could also mean that code blocks that never run again after being
1106 // compiled would sit on the worklist until next GC. That's fine, but it's
1107 // probably a waste of memory. Our goal here is to complete code blocks as soon as
1108 // possible in order to minimize the chances of us executing baseline code after
1109 // optimized code is already available.
msaboff@apple.com95894332014-01-29 19:18:54 +00001110 worklistState = worklist->completeAllReadyPlansForVM(
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001111 vm, DFG::CompilationKey(codeBlock, DFG::DFGMode));
1112 } else
1113 worklistState = DFG::Worklist::NotKnown;
1114
1115 if (worklistState == DFG::Worklist::Compiling) {
1116 // We cannot be in the process of asynchronous compilation and also have an optimized
1117 // replacement.
1118 RELEASE_ASSERT(!codeBlock->hasOptimizedReplacement());
1119 codeBlock->setOptimizationThresholdBasedOnCompilationResult(CompilationDeferred);
msaboff@apple.com95894332014-01-29 19:18:54 +00001120 return encodeResult(0, 0);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001121 }
1122
1123 if (worklistState == DFG::Worklist::Compiled) {
1124 // If we don't have an optimized replacement but we did just get compiled, then
1125 // the compilation failed or was invalidated, in which case the execution count
1126 // thresholds have already been set appropriately by
1127 // CodeBlock::setOptimizationThresholdBasedOnCompilationResult() and we have
1128 // nothing left to do.
1129 if (!codeBlock->hasOptimizedReplacement()) {
1130 codeBlock->updateAllPredictions();
1131 if (Options::verboseOSR())
1132 dataLog("Code block ", *codeBlock, " was compiled but it doesn't have an optimized replacement.\n");
msaboff@apple.com95894332014-01-29 19:18:54 +00001133 return encodeResult(0, 0);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001134 }
1135 } else if (codeBlock->hasOptimizedReplacement()) {
1136 if (Options::verboseOSR())
1137 dataLog("Considering OSR ", *codeBlock, " -> ", *codeBlock->replacement(), ".\n");
1138 // If we have an optimized replacement, then it must be the case that we entered
1139 // cti_optimize from a loop. That's because if there's an optimized replacement,
1140 // then all calls to this function will be relinked to the replacement and so
1141 // the prologue OSR will never fire.
1142
1143 // This is an interesting threshold check. Consider that a function OSR exits
1144 // in the middle of a loop, while having a relatively low exit count. The exit
1145 // will reset the execution counter to some target threshold, meaning that this
1146 // code won't be reached until that loop heats up for >=1000 executions. But then
1147 // we do a second check here, to see if we should either reoptimize, or just
1148 // attempt OSR entry. Hence it might even be correct for
1149 // shouldReoptimizeFromLoopNow() to always return true. But we make it do some
1150 // additional checking anyway, to reduce the amount of recompilation thrashing.
1151 if (codeBlock->replacement()->shouldReoptimizeFromLoopNow()) {
1152 if (Options::verboseOSR()) {
1153 dataLog(
1154 "Triggering reoptimization of ", *codeBlock,
1155 "(", *codeBlock->replacement(), ") (in loop).\n");
1156 }
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00001157 codeBlock->replacement()->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTrigger, CountReoptimization);
msaboff@apple.com95894332014-01-29 19:18:54 +00001158 return encodeResult(0, 0);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001159 }
1160 } else {
1161 if (!codeBlock->shouldOptimizeNow()) {
1162 if (Options::verboseOSR()) {
1163 dataLog(
1164 "Delaying optimization for ", *codeBlock,
1165 " because of insufficient profiling.\n");
1166 }
msaboff@apple.com95894332014-01-29 19:18:54 +00001167 return encodeResult(0, 0);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001168 }
1169
1170 if (Options::verboseOSR())
1171 dataLog("Triggering optimized compilation of ", *codeBlock, "\n");
1172
1173 unsigned numVarsWithValues;
1174 if (bytecodeIndex)
1175 numVarsWithValues = codeBlock->m_numVars;
1176 else
1177 numVarsWithValues = 0;
1178 Operands<JSValue> mustHandleValues(codeBlock->numParameters(), numVarsWithValues);
1179 for (size_t i = 0; i < mustHandleValues.size(); ++i) {
1180 int operand = mustHandleValues.operandForIndex(i);
1181 if (operandIsArgument(operand)
1182 && !VirtualRegister(operand).toArgument()
1183 && codeBlock->codeType() == FunctionCode
1184 && codeBlock->specializationKind() == CodeForConstruct) {
1185 // Ugh. If we're in a constructor, the 'this' argument may hold garbage. It will
1186 // also never be used. It doesn't matter what we put into the value for this,
1187 // but it has to be an actual value that can be grokked by subsequent DFG passes,
1188 // so we sanitize it here by turning it into Undefined.
1189 mustHandleValues[i] = jsUndefined();
1190 } else
1191 mustHandleValues[i] = exec->uncheckedR(operand).jsValue();
1192 }
1193
mark.lam@apple.comaebf6852014-03-03 21:39:21 +00001194 RefPtr<CodeBlock> replacementCodeBlock = codeBlock->newReplacement();
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001195 CompilationResult result = DFG::compile(
mark.lam@apple.comaebf6852014-03-03 21:39:21 +00001196 vm, replacementCodeBlock.get(), 0, DFG::DFGMode, bytecodeIndex,
msaboff@apple.com95894332014-01-29 19:18:54 +00001197 mustHandleValues, JITToDFGDeferredCompilationCallback::create());
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001198
mark.lam@apple.comaebf6852014-03-03 21:39:21 +00001199 if (result != CompilationSuccessful) {
1200 ASSERT(result == CompilationDeferred || replacementCodeBlock->hasOneRef());
msaboff@apple.com95894332014-01-29 19:18:54 +00001201 return encodeResult(0, 0);
mark.lam@apple.comaebf6852014-03-03 21:39:21 +00001202 }
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001203 }
1204
1205 CodeBlock* optimizedCodeBlock = codeBlock->replacement();
1206 ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
1207
fpizlo@apple.com6fd929f2014-02-17 06:25:05 +00001208 if (void* dataBuffer = DFG::prepareOSREntry(exec, optimizedCodeBlock, bytecodeIndex)) {
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001209 if (Options::verboseOSR()) {
1210 dataLog(
fpizlo@apple.com6fd929f2014-02-17 06:25:05 +00001211 "Performing OSR ", *codeBlock, " -> ", *optimizedCodeBlock, ".\n");
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001212 }
1213
1214 codeBlock->optimizeSoon();
fpizlo@apple.com6fd929f2014-02-17 06:25:05 +00001215 return encodeResult(vm.getCTIStub(DFG::osrEntryThunkGenerator).code().executableAddress(), dataBuffer);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001216 }
1217
1218 if (Options::verboseOSR()) {
1219 dataLog(
1220 "Optimizing ", *codeBlock, " -> ", *codeBlock->replacement(),
1221 " succeeded, OSR failed, after a delay of ",
1222 codeBlock->optimizationDelayCounter(), ".\n");
1223 }
1224
1225 // Count the OSR failure as a speculation failure. If this happens a lot, then
1226 // reoptimize.
1227 optimizedCodeBlock->countOSRExit();
1228
1229 // We are a lot more conservative about triggering reoptimization after OSR failure than
1230 // before it. If we enter the optimize_from_loop trigger with a bucket full of fail
1231 // already, then we really would like to reoptimize immediately. But this case covers
1232 // something else: there weren't many (or any) speculation failures before, but we just
1233 // failed to enter the speculative code because some variable had the wrong value or
1234 // because the OSR code decided for any spurious reason that it did not want to OSR
1235 // right now. So, we only trigger reoptimization only upon the more conservative (non-loop)
1236 // reoptimization trigger.
1237 if (optimizedCodeBlock->shouldReoptimizeNow()) {
1238 if (Options::verboseOSR()) {
1239 dataLog(
1240 "Triggering reoptimization of ", *codeBlock, " -> ",
1241 *codeBlock->replacement(), " (after OSR fail).\n");
1242 }
fpizlo@apple.com0dda6d72014-02-02 02:25:13 +00001243 optimizedCodeBlock->jettison(Profiler::JettisonDueToBaselineLoopReoptimizationTriggerOnOSREntryFail, CountReoptimization);
msaboff@apple.com95894332014-01-29 19:18:54 +00001244 return encodeResult(0, 0);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001245 }
1246
1247 // OSR failed this time, but it might succeed next time! Let the code run a bit
1248 // longer and then try again.
1249 codeBlock->optimizeAfterWarmUp();
1250
msaboff@apple.com95894332014-01-29 19:18:54 +00001251 return encodeResult(0, 0);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001252}
1253#endif
1254
1255void JIT_OPERATION operationPutByIndex(ExecState* exec, EncodedJSValue encodedArrayValue, int32_t index, EncodedJSValue encodedValue)
1256{
1257 VM& vm = exec->vm();
1258 NativeCallFrameTracer tracer(&vm, exec);
1259
1260 JSValue arrayValue = JSValue::decode(encodedArrayValue);
1261 ASSERT(isJSArray(arrayValue));
1262 asArray(arrayValue)->putDirectIndex(exec, index, JSValue::decode(encodedValue));
1263}
1264
1265#if USE(JSVALUE64)
1266void JIT_OPERATION operationPutGetterSetter(ExecState* exec, EncodedJSValue encodedObjectValue, Identifier* identifier, EncodedJSValue encodedGetterValue, EncodedJSValue encodedSetterValue)
1267{
1268 VM& vm = exec->vm();
1269 NativeCallFrameTracer tracer(&vm, exec);
1270
1271 ASSERT(JSValue::decode(encodedObjectValue).isObject());
1272 JSObject* baseObj = asObject(JSValue::decode(encodedObjectValue));
1273
1274 GetterSetter* accessor = GetterSetter::create(vm);
1275
1276 JSValue getter = JSValue::decode(encodedGetterValue);
1277 JSValue setter = JSValue::decode(encodedSetterValue);
1278 ASSERT(getter.isObject() || getter.isUndefined());
1279 ASSERT(setter.isObject() || setter.isUndefined());
1280 ASSERT(getter.isObject() || setter.isObject());
1281
1282 if (!getter.isUndefined())
1283 accessor->setGetter(vm, asObject(getter));
1284 if (!setter.isUndefined())
1285 accessor->setSetter(vm, asObject(setter));
1286 baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
1287}
1288#else
1289void JIT_OPERATION operationPutGetterSetter(ExecState* exec, JSCell* object, Identifier* identifier, JSCell* getter, JSCell* setter)
1290{
1291 VM& vm = exec->vm();
1292 NativeCallFrameTracer tracer(&vm, exec);
1293
1294 ASSERT(object && object->isObject());
1295 JSObject* baseObj = object->getObject();
1296
1297 GetterSetter* accessor = GetterSetter::create(vm);
1298
1299 ASSERT(!getter || getter->isObject());
1300 ASSERT(!setter || setter->isObject());
1301 ASSERT(getter || setter);
1302
1303 if (getter)
1304 accessor->setGetter(vm, getter->getObject());
1305 if (setter)
1306 accessor->setSetter(vm, setter->getObject());
1307 baseObj->putDirectAccessor(exec, *identifier, accessor, Accessor);
1308}
1309#endif
1310
msaboff@apple.com6c3a18d2014-11-07 21:58:43 +00001311void JIT_OPERATION operationPushNameScope(ExecState* exec, int32_t dst, Identifier* identifier, EncodedJSValue encodedValue, int32_t attibutes, int32_t type)
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001312{
1313 VM& vm = exec->vm();
1314 NativeCallFrameTracer tracer(&vm, exec);
1315
mark.lam@apple.comb1ed12b2014-10-02 15:15:03 +00001316 JSNameScope::Type scopeType = static_cast<JSNameScope::Type>(type);
1317 JSNameScope* scope = JSNameScope::create(exec, *identifier, JSValue::decode(encodedValue), attibutes, scopeType);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001318
msaboff@apple.com6c3a18d2014-11-07 21:58:43 +00001319 exec->uncheckedR(dst) = scope;
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001320}
1321
msaboff@apple.com6c3a18d2014-11-07 21:58:43 +00001322#if USE(JSVALUE32_64)
1323void JIT_OPERATION operationPushCatchScope(ExecState* exec, int32_t dst, Identifier* identifier, EncodedJSValue encodedValue, int32_t attibutes)
1324{
1325 operationPushNameScope(exec, dst, identifier, encodedValue, attibutes, JSNameScope::CatchScope);
1326}
1327
1328void JIT_OPERATION operationPushFunctionNameScope(ExecState* exec, int32_t dst, Identifier* identifier, EncodedJSValue encodedValue, int32_t attibutes)
1329{
1330 operationPushNameScope(exec, dst, identifier, encodedValue, attibutes, JSNameScope::FunctionNameScope);
1331}
1332#endif
1333
1334void JIT_OPERATION operationPushWithScope(ExecState* exec, int32_t dst, EncodedJSValue encodedValue)
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001335{
1336 VM& vm = exec->vm();
1337 NativeCallFrameTracer tracer(&vm, exec);
1338
1339 JSObject* o = JSValue::decode(encodedValue).toObject(exec);
1340 if (vm.exception())
1341 return;
1342
msaboff@apple.com6c3a18d2014-11-07 21:58:43 +00001343 exec->uncheckedR(dst) = JSWithScope::create(exec, o);
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001344}
1345
msaboff@apple.com6c3a18d2014-11-07 21:58:43 +00001346void JIT_OPERATION operationPopScope(ExecState* exec, int32_t scopeReg)
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001347{
1348 VM& vm = exec->vm();
1349 NativeCallFrameTracer tracer(&vm, exec);
1350
msaboff@apple.com6c3a18d2014-11-07 21:58:43 +00001351 JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
1352 exec->uncheckedR(scopeReg) = scope->next();
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001353}
1354
1355void JIT_OPERATION operationProfileDidCall(ExecState* exec, EncodedJSValue encodedValue)
1356{
1357 VM& vm = exec->vm();
1358 NativeCallFrameTracer tracer(&vm, exec);
1359
1360 if (LegacyProfiler* profiler = vm.enabledProfiler())
1361 profiler->didExecute(exec, JSValue::decode(encodedValue));
1362}
1363
1364void JIT_OPERATION operationProfileWillCall(ExecState* exec, EncodedJSValue encodedValue)
1365{
1366 VM& vm = exec->vm();
1367 NativeCallFrameTracer tracer(&vm, exec);
1368
1369 if (LegacyProfiler* profiler = vm.enabledProfiler())
1370 profiler->willExecute(exec, JSValue::decode(encodedValue));
1371}
1372
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001373EncodedJSValue JIT_OPERATION operationCheckHasInstance(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedBaseVal)
1374{
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00001375 VM& vm = exec->vm();
1376 NativeCallFrameTracer tracer(&vm, exec);
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001377
1378 JSValue value = JSValue::decode(encodedValue);
1379 JSValue baseVal = JSValue::decode(encodedBaseVal);
1380
1381 if (baseVal.isObject()) {
1382 JSObject* baseObject = asObject(baseVal);
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00001383 ASSERT(!baseObject->structure(vm)->typeInfo().implementsDefaultHasInstance());
1384 if (baseObject->structure(vm)->typeInfo().implementsHasInstance()) {
1385 bool result = baseObject->methodTable(vm)->customHasInstance(baseObject, exec, value);
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001386 return JSValue::encode(jsBoolean(result));
1387 }
1388 }
1389
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00001390 vm.throwException(exec, createInvalidParameterError(exec, "instanceof", baseVal));
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001391 return JSValue::encode(JSValue());
1392}
1393
1394JSCell* JIT_OPERATION operationCreateActivation(ExecState* exec, int32_t offset)
1395{
1396 VM& vm = exec->vm();
1397 NativeCallFrameTracer tracer(&vm, exec);
oliver@apple.coma7dfb4d2014-09-11 18:18:14 +00001398 JSLexicalEnvironment* lexicalEnvironment = JSLexicalEnvironment::create(vm, exec, exec->registers() + offset, exec->codeBlock());
1399 exec->setScope(lexicalEnvironment);
1400 return lexicalEnvironment;
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001401}
1402
1403JSCell* JIT_OPERATION operationCreateArguments(ExecState* exec)
1404{
1405 VM& vm = exec->vm();
1406 NativeCallFrameTracer tracer(&vm, exec);
1407 // NB: This needs to be exceedingly careful with top call frame tracking, since it
1408 // may be called from OSR exit, while the state of the call stack is bizarre.
1409 Arguments* result = Arguments::create(vm, exec);
1410 ASSERT(!vm.exception());
1411 return result;
1412}
1413
msaboff@apple.com4c296302014-06-14 17:43:32 +00001414JSCell* JIT_OPERATION operationCreateArgumentsDuringOSRExit(ExecState* exec)
1415{
1416 DeferGCForAWhile(exec->vm().heap);
1417 return operationCreateArguments(exec);
1418}
1419
mark.lam@apple.com65293072013-10-17 07:20:20 +00001420EncodedJSValue JIT_OPERATION operationGetArgumentsLength(ExecState* exec, int32_t argumentsRegister)
1421{
1422 VM& vm = exec->vm();
1423 NativeCallFrameTracer tracer(&vm, exec);
1424 // Here we can assume that the argumernts were created. Because otherwise the JIT code would
1425 // have not made this call.
1426 Identifier ident(&vm, "length");
1427 JSValue baseValue = exec->uncheckedR(argumentsRegister).jsValue();
1428 PropertySlot slot(baseValue);
1429 return JSValue::encode(baseValue.get(exec, ident, slot));
1430}
1431
bfulgham@apple.com283982c2013-12-06 22:56:46 +00001432}
1433
mark.lam@apple.com65293072013-10-17 07:20:20 +00001434static JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript, ReturnAddressPtr returnAddress)
1435{
1436 if (LIKELY(baseValue.isCell() && subscript.isString())) {
akling@apple.combaca5e82014-05-06 00:53:29 +00001437 VM& vm = exec->vm();
1438 Structure& structure = *baseValue.asCell()->structure(vm);
1439 if (JSCell::canUseFastGetOwnProperty(structure)) {
akling@apple.comcad89042014-09-02 22:29:59 +00001440 if (AtomicStringImpl* existingAtomicString = asString(subscript)->toExistingAtomicString(exec)) {
1441 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, existingAtomicString))
1442 return result;
1443 }
akling@apple.combaca5e82014-05-06 00:53:29 +00001444 }
mark.lam@apple.com65293072013-10-17 07:20:20 +00001445 }
1446
1447 if (subscript.isUInt32()) {
1448 uint32_t i = subscript.asUInt32();
1449 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) {
1450 ctiPatchCallByReturnAddress(exec->codeBlock(), returnAddress, FunctionPtr(operationGetByValString));
1451 return asString(baseValue)->getIndex(exec, i);
1452 }
1453 return baseValue.get(exec, i);
1454 }
1455
1456 if (isName(subscript))
1457 return baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
1458
akling@apple.combaca5e82014-05-06 00:53:29 +00001459 Identifier property = subscript.toString(exec)->toIdentifier(exec);
mark.lam@apple.com65293072013-10-17 07:20:20 +00001460 return baseValue.get(exec, property);
1461}
1462
bfulgham@apple.com283982c2013-12-06 22:56:46 +00001463extern "C" {
1464
mark.lam@apple.com65293072013-10-17 07:20:20 +00001465EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1466{
1467 VM& vm = exec->vm();
1468 NativeCallFrameTracer tracer(&vm, exec);
1469 JSValue baseValue = JSValue::decode(encodedBase);
1470 JSValue subscript = JSValue::decode(encodedSubscript);
1471
1472 JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
1473 return JSValue::encode(result);
1474}
1475
1476EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1477{
1478 VM& vm = exec->vm();
1479 NativeCallFrameTracer tracer(&vm, exec);
1480 JSValue baseValue = JSValue::decode(encodedBase);
1481 JSValue subscript = JSValue::decode(encodedSubscript);
1482
1483 if (baseValue.isObject() && subscript.isInt32()) {
1484 // See if it's worth optimizing this at all.
1485 JSObject* object = asObject(baseValue);
1486 bool didOptimize = false;
1487
1488 unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
1489 ASSERT(bytecodeOffset);
1490 ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
1491 ASSERT(!byValInfo.stubRoutine);
1492
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00001493 if (hasOptimizableIndexing(object->structure(vm))) {
mark.lam@apple.com65293072013-10-17 07:20:20 +00001494 // Attempt to optimize.
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00001495 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
mark.lam@apple.com65293072013-10-17 07:20:20 +00001496 if (arrayMode != byValInfo.arrayMode) {
1497 JIT::compileGetByVal(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
1498 didOptimize = true;
1499 }
1500 }
1501
1502 if (!didOptimize) {
1503 // If we take slow path more than 10 times without patching then make sure we
1504 // never make that mistake again. Or, if we failed to patch and we have some object
1505 // that intercepts indexed get, then don't even wait until 10 times. For cases
1506 // where we see non-index-intercepting objects, this gives 10 iterations worth of
1507 // opportunity for us to observe that the get_by_val may be polymorphic.
1508 if (++byValInfo.slowPathCount >= 10
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00001509 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
mark.lam@apple.com65293072013-10-17 07:20:20 +00001510 // Don't ever try to optimize.
1511 RepatchBuffer repatchBuffer(exec->codeBlock());
1512 repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValGeneric));
1513 }
1514 }
1515 }
1516
1517 JSValue result = getByVal(exec, baseValue, subscript, ReturnAddressPtr(OUR_RETURN_ADDRESS));
1518 return JSValue::encode(result);
1519}
1520
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001521EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1522{
1523 VM& vm = exec->vm();
1524 NativeCallFrameTracer tracer(&vm, exec);
1525 JSValue baseValue = JSValue::decode(encodedBase);
1526 JSValue subscript = JSValue::decode(encodedSubscript);
1527
1528 ASSERT(baseValue.isObject());
1529 ASSERT(subscript.isUInt32());
1530
1531 JSObject* object = asObject(baseValue);
1532 bool didOptimize = false;
1533
1534 unsigned bytecodeOffset = exec->locationAsBytecodeOffset();
1535 ASSERT(bytecodeOffset);
1536 ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
1537 ASSERT(!byValInfo.stubRoutine);
1538
1539 if (hasOptimizableIndexing(object->structure(vm))) {
1540 // Attempt to optimize.
1541 JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
1542 if (arrayMode != byValInfo.arrayMode) {
1543 JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), &byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
1544 didOptimize = true;
1545 }
1546 }
1547
1548 if (!didOptimize) {
1549 // If we take slow path more than 10 times without patching then make sure we
1550 // never make that mistake again. Or, if we failed to patch and we have some object
1551 // that intercepts indexed get, then don't even wait until 10 times. For cases
1552 // where we see non-index-intercepting objects, this gives 10 iterations worth of
1553 // opportunity for us to observe that the get_by_val may be polymorphic.
1554 if (++byValInfo.slowPathCount >= 10
1555 || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
1556 // Don't ever try to optimize.
1557 RepatchBuffer repatchBuffer(exec->codeBlock());
1558 repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric));
1559 }
1560 }
1561
1562 return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
1563}
1564
1565EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1566{
1567 VM& vm = exec->vm();
1568 NativeCallFrameTracer tracer(&vm, exec);
1569 JSValue baseValue = JSValue::decode(encodedBase);
1570 JSValue subscript = JSValue::decode(encodedSubscript);
1571
1572 ASSERT(baseValue.isObject());
1573 ASSERT(subscript.isUInt32());
1574
1575 JSObject* object = asObject(baseValue);
1576 return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
1577}
1578
mark.lam@apple.com65293072013-10-17 07:20:20 +00001579EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
1580{
1581 VM& vm = exec->vm();
1582 NativeCallFrameTracer tracer(&vm, exec);
1583 JSValue baseValue = JSValue::decode(encodedBase);
1584 JSValue subscript = JSValue::decode(encodedSubscript);
1585
1586 JSValue result;
1587 if (LIKELY(subscript.isUInt32())) {
1588 uint32_t i = subscript.asUInt32();
1589 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i))
1590 result = asString(baseValue)->getIndex(exec, i);
1591 else {
1592 result = baseValue.get(exec, i);
1593 if (!isJSString(baseValue))
1594 ctiPatchCallByReturnAddress(exec->codeBlock(), ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationGetByValDefault));
1595 }
1596 } else if (isName(subscript))
1597 result = baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName());
1598 else {
akling@apple.combaca5e82014-05-06 00:53:29 +00001599 Identifier property = subscript.toString(exec)->toIdentifier(exec);
mark.lam@apple.com65293072013-10-17 07:20:20 +00001600 result = baseValue.get(exec, property);
1601 }
1602
1603 return JSValue::encode(result);
1604}
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001605
oliver@apple.com1f26a182014-10-06 19:29:27 +00001606void JIT_OPERATION operationTearOffArguments(ExecState* exec, JSCell* argumentsCell, JSCell*)
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001607{
1608 ASSERT(exec->codeBlock()->usesArguments());
msaboff@apple.com4b6250f2013-10-15 18:33:04 +00001609 jsCast<Arguments*>(argumentsCell)->tearOff(exec);
1610}
1611
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001612EncodedJSValue JIT_OPERATION operationDeleteById(ExecState* exec, EncodedJSValue encodedBase, const Identifier* identifier)
1613{
1614 VM& vm = exec->vm();
1615 NativeCallFrameTracer tracer(&vm, exec);
1616
1617 JSObject* baseObj = JSValue::decode(encodedBase).toObject(exec);
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00001618 bool couldDelete = baseObj->methodTable(vm)->deleteProperty(baseObj, exec, *identifier);
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001619 JSValue result = jsBoolean(couldDelete);
1620 if (!couldDelete && exec->codeBlock()->isStrictMode())
commit-queue@webkit.org29e710c2014-08-29 21:33:30 +00001621 vm.throwException(exec, createTypeError(exec, ASCIILiteral("Unable to delete property.")));
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001622 return JSValue::encode(result);
1623}
1624
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001625EncodedJSValue JIT_OPERATION operationInstanceOf(ExecState* exec, EncodedJSValue encodedValue, EncodedJSValue encodedProto)
1626{
1627 VM& vm = exec->vm();
1628 NativeCallFrameTracer tracer(&vm, exec);
1629 JSValue value = JSValue::decode(encodedValue);
1630 JSValue proto = JSValue::decode(encodedProto);
1631
1632 ASSERT(!value.isObject() || !proto.isObject());
1633
1634 bool result = JSObject::defaultHasInstance(exec, value, proto);
1635 return JSValue::encode(jsBoolean(result));
1636}
1637
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001638CallFrame* JIT_OPERATION operationSizeFrameForVarargs(ExecState* exec, EncodedJSValue encodedArguments, int32_t firstFreeRegister, int32_t firstVarArgOffset)
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001639{
1640 VM& vm = exec->vm();
1641 NativeCallFrameTracer tracer(&vm, exec);
1642 JSStack* stack = &exec->interpreter()->stack();
msaboff@apple.com75cc9322013-12-06 21:38:26 +00001643 JSValue arguments = JSValue::decode(encodedArguments);
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001644 CallFrame* newCallFrame = sizeFrameForVarargs(exec, stack, arguments, firstFreeRegister, firstVarArgOffset);
msaboff@apple.com75cc9322013-12-06 21:38:26 +00001645 return newCallFrame;
1646}
1647
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001648CallFrame* JIT_OPERATION operationLoadVarargs(ExecState* exec, CallFrame* newCallFrame, EncodedJSValue encodedThis, EncodedJSValue encodedArguments, int32_t firstVarArgOffset)
msaboff@apple.com75cc9322013-12-06 21:38:26 +00001649{
1650 VM& vm = exec->vm();
1651 NativeCallFrameTracer tracer(&vm, exec);
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001652 JSValue thisValue = JSValue::decode(encodedThis);
1653 JSValue arguments = JSValue::decode(encodedArguments);
oliver@apple.com2f5c83b2014-02-25 06:59:38 +00001654 loadVarargs(exec, newCallFrame, thisValue, arguments, firstVarArgOffset);
mark.lam@apple.com03944a02013-10-14 16:42:22 +00001655 return newCallFrame;
1656}
1657
1658EncodedJSValue JIT_OPERATION operationToObject(ExecState* exec, EncodedJSValue value)
1659{
1660 VM& vm = exec->vm();
1661 NativeCallFrameTracer tracer(&vm, exec);
1662 return JSValue::encode(JSValue::decode(value).toObject(exec));
1663}
1664
mark.lam@apple.com2a90d902013-10-15 03:03:45 +00001665char* JIT_OPERATION operationSwitchCharWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1666{
1667 VM& vm = exec->vm();
1668 NativeCallFrameTracer tracer(&vm, exec);
1669 JSValue key = JSValue::decode(encodedKey);
1670 CodeBlock* codeBlock = exec->codeBlock();
1671
1672 SimpleJumpTable& jumpTable = codeBlock->switchJumpTable(tableIndex);
1673 void* result = jumpTable.ctiDefault.executableAddress();
1674
1675 if (key.isString()) {
1676 StringImpl* value = asString(key)->value(exec).impl();
1677 if (value->length() == 1)
1678 result = jumpTable.ctiForValue((*value)[0]).executableAddress();
1679 }
1680
1681 return reinterpret_cast<char*>(result);
1682}
1683
1684char* JIT_OPERATION operationSwitchImmWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1685{
1686 VM& vm = exec->vm();
1687 NativeCallFrameTracer tracer(&vm, exec);
1688 JSValue key = JSValue::decode(encodedKey);
1689 CodeBlock* codeBlock = exec->codeBlock();
1690
1691 SimpleJumpTable& jumpTable = codeBlock->switchJumpTable(tableIndex);
1692 void* result;
1693 if (key.isInt32())
1694 result = jumpTable.ctiForValue(key.asInt32()).executableAddress();
1695 else if (key.isDouble() && key.asDouble() == static_cast<int32_t>(key.asDouble()))
1696 result = jumpTable.ctiForValue(static_cast<int32_t>(key.asDouble())).executableAddress();
1697 else
1698 result = jumpTable.ctiDefault.executableAddress();
1699 return reinterpret_cast<char*>(result);
1700}
1701
1702char* JIT_OPERATION operationSwitchStringWithUnknownKeyType(ExecState* exec, EncodedJSValue encodedKey, size_t tableIndex)
1703{
1704 VM& vm = exec->vm();
1705 NativeCallFrameTracer tracer(&vm, exec);
1706 JSValue key = JSValue::decode(encodedKey);
1707 CodeBlock* codeBlock = exec->codeBlock();
1708
1709 void* result;
1710 StringJumpTable& jumpTable = codeBlock->stringSwitchJumpTable(tableIndex);
1711
1712 if (key.isString()) {
1713 StringImpl* value = asString(key)->value(exec).impl();
1714 result = jumpTable.ctiForValue(value).executableAddress();
1715 } else
1716 result = jumpTable.ctiDefault.executableAddress();
1717
1718 return reinterpret_cast<char*>(result);
1719}
1720
msaboff@apple.com80cde942014-11-12 02:33:43 +00001721EncodedJSValue JIT_OPERATION operationResolveScope(ExecState* exec, int32_t scopeReg, int32_t identifierIndex)
mark.lam@apple.com2a90d902013-10-15 03:03:45 +00001722{
1723 VM& vm = exec->vm();
1724 NativeCallFrameTracer tracer(&vm, exec);
1725 const Identifier& ident = exec->codeBlock()->identifier(identifierIndex);
msaboff@apple.com80cde942014-11-12 02:33:43 +00001726 JSScope* scope = exec->uncheckedR(scopeReg).Register::scope();
1727 return JSValue::encode(JSScope::resolve(exec, scope, ident));
mark.lam@apple.com2a90d902013-10-15 03:03:45 +00001728}
1729
1730EncodedJSValue JIT_OPERATION operationGetFromScope(ExecState* exec, Instruction* bytecodePC)
1731{
1732 VM& vm = exec->vm();
1733 NativeCallFrameTracer tracer(&vm, exec);
1734 CodeBlock* codeBlock = exec->codeBlock();
1735 Instruction* pc = bytecodePC;
1736
1737 const Identifier& ident = codeBlock->identifier(pc[3].u.operand);
1738 JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[2].u.operand).jsValue());
1739 ResolveModeAndType modeAndType(pc[4].u.operand);
1740
1741 PropertySlot slot(scope);
1742 if (!scope->getPropertySlot(exec, ident, slot)) {
1743 if (modeAndType.mode() == ThrowIfNotFound)
1744 vm.throwException(exec, createUndefinedVariableError(exec, ident));
1745 return JSValue::encode(jsUndefined());
1746 }
1747
1748 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
mhahnenberg@apple.comb6f85192014-02-27 01:27:18 +00001749 if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure(vm)->propertyAccessesAreCacheable()) {
mark.lam@apple.com2a90d902013-10-15 03:03:45 +00001750 if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001751 Structure* structure = scope->structure(vm);
1752 {
1753 ConcurrentJITLocker locker(codeBlock->m_lock);
1754 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure);
1755 pc[6].u.operand = slot.cachedOffset();
1756 }
1757 structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
mark.lam@apple.com2a90d902013-10-15 03:03:45 +00001758 }
1759 }
1760
1761 return JSValue::encode(slot.getValue(exec, ident));
1762}
1763
1764void JIT_OPERATION operationPutToScope(ExecState* exec, Instruction* bytecodePC)
1765{
1766 VM& vm = exec->vm();
1767 NativeCallFrameTracer tracer(&vm, exec);
1768 Instruction* pc = bytecodePC;
1769
1770 CodeBlock* codeBlock = exec->codeBlock();
1771 const Identifier& ident = codeBlock->identifier(pc[2].u.operand);
1772 JSObject* scope = jsCast<JSObject*>(exec->uncheckedR(pc[1].u.operand).jsValue());
1773 JSValue value = exec->r(pc[3].u.operand).jsValue();
1774 ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand);
oliver@apple.comf129dfb2014-10-02 20:35:58 +00001775 if (modeAndType.type() == LocalClosureVar) {
1776 JSLexicalEnvironment* environment = jsCast<JSLexicalEnvironment*>(scope);
1777 environment->registerAt(pc[6].u.operand).set(vm, environment, value);
1778 if (VariableWatchpointSet* set = pc[5].u.watchpointSet)
1779 set->notifyWrite(vm, value, "Executed op_put_scope<LocalClosureVar>");
1780 return;
1781 }
mark.lam@apple.com2a90d902013-10-15 03:03:45 +00001782 if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) {
1783 exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
1784 return;
1785 }
1786
oliver@apple.com68848412014-01-02 20:56:20 +00001787 PutPropertySlot slot(scope, codeBlock->isStrictMode());
mark.lam@apple.com2a90d902013-10-15 03:03:45 +00001788 scope->methodTable()->put(scope, exec, ident, value, slot);
1789
1790 if (exec->vm().exception())
1791 return;
1792
fpizlo@apple.com2c4a7e92014-08-06 05:27:46 +00001793 CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot);
mark.lam@apple.com2a90d902013-10-15 03:03:45 +00001794}
1795
msaboff@apple.combdfcf6a2013-10-18 16:25:02 +00001796void JIT_OPERATION operationThrow(ExecState* exec, EncodedJSValue encodedExceptionValue)
msaboff@apple.comf8813812013-10-17 18:12:28 +00001797{
1798 VM* vm = &exec->vm();
1799 NativeCallFrameTracer tracer(vm, exec);
1800
1801 JSValue exceptionValue = JSValue::decode(encodedExceptionValue);
1802 vm->throwException(exec, exceptionValue);
msaboff@apple.combdfcf6a2013-10-18 16:25:02 +00001803
msaboff@apple.com0576b242014-08-22 19:54:30 +00001804 // Results stored out-of-band in vm.targetMachinePCForThrow, vm.callFrameForThrow & vm.vmEntryFrameForThrow
msaboff@apple.combdfcf6a2013-10-18 16:25:02 +00001805 genericUnwind(vm, exec, exceptionValue);
msaboff@apple.comf8813812013-10-17 18:12:28 +00001806}
1807
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001808void JIT_OPERATION operationFlushWriteBarrierBuffer(ExecState* exec, JSCell* cell)
1809{
1810 VM* vm = &exec->vm();
1811 NativeCallFrameTracer tracer(vm, exec);
1812 vm->heap.flushWriteBarrierBuffer(cell);
1813}
1814
1815void JIT_OPERATION operationOSRWriteBarrier(ExecState* exec, JSCell* cell)
1816{
1817 VM* vm = &exec->vm();
1818 NativeCallFrameTracer tracer(vm, exec);
mhahnenberg@apple.comb8194fa2014-02-07 00:42:21 +00001819 vm->heap.writeBarrier(cell);
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001820}
1821
1822// NB: We don't include the value as part of the barrier because the write barrier elision
1823// phase in the DFG only tracks whether the object being stored to has been barriered. It
1824// would be much more complicated to try to model the value being stored as well.
1825void JIT_OPERATION operationUnconditionalWriteBarrier(ExecState* exec, JSCell* cell)
1826{
1827 VM* vm = &exec->vm();
1828 NativeCallFrameTracer tracer(vm, exec);
mhahnenberg@apple.comb8194fa2014-02-07 00:42:21 +00001829 vm->heap.writeBarrier(cell);
mhahnenberg@apple.com4968e1a2013-12-18 22:50:40 +00001830}
1831
1832void JIT_OPERATION operationInitGlobalConst(ExecState* exec, Instruction* pc)
1833{
1834 VM* vm = &exec->vm();
1835 NativeCallFrameTracer tracer(vm, exec);
1836
1837 JSValue value = exec->r(pc[2].u.operand).jsValue();
1838 pc[1].u.registerPointer->set(*vm, exec->codeBlock()->globalObject(), value);
1839}
1840
msaboff@apple.com95894332014-01-29 19:18:54 +00001841void JIT_OPERATION lookupExceptionHandler(VM* vm, ExecState* exec)
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00001842{
msaboff@apple.com4d563e42014-08-16 01:45:40 +00001843 NativeCallFrameTracer tracer(vm, exec);
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00001844
msaboff@apple.com95894332014-01-29 19:18:54 +00001845 JSValue exceptionValue = vm->exception();
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00001846 ASSERT(exceptionValue);
1847
msaboff@apple.combdfcf6a2013-10-18 16:25:02 +00001848 genericUnwind(vm, exec, exceptionValue);
1849 ASSERT(vm->targetMachinePCForThrow);
1850}
1851
msaboff@apple.com0576b242014-08-22 19:54:30 +00001852void JIT_OPERATION lookupExceptionHandlerFromCallerFrame(VM* vm, ExecState* exec)
1853{
1854 VMEntryFrame* vmEntryFrame = vm->topVMEntryFrame;
1855 CallFrame* callerFrame = exec->callerFrame(vmEntryFrame);
1856 ASSERT(callerFrame);
1857
msaboff@apple.com76131802014-08-25 19:32:40 +00001858 NativeCallFrameTracerWithRestore tracer(vm, vmEntryFrame, callerFrame);
msaboff@apple.com0576b242014-08-22 19:54:30 +00001859
1860 JSValue exceptionValue = vm->exception();
1861 ASSERT(exceptionValue);
1862
1863 genericUnwind(vm, callerFrame, exceptionValue);
1864 ASSERT(vm->targetMachinePCForThrow);
1865}
1866
msaboff@apple.combdfcf6a2013-10-18 16:25:02 +00001867void JIT_OPERATION operationVMHandleException(ExecState* exec)
1868{
1869 VM* vm = &exec->vm();
1870 NativeCallFrameTracer tracer(vm, exec);
1871
msaboff@apple.combdfcf6a2013-10-18 16:25:02 +00001872 genericUnwind(vm, exec, vm->exception());
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00001873}
1874
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +00001875// This function "should" just take the ExecState*, but doing so would make it more difficult
1876// to call from exception check sites. So, unlike all of our other functions, we allow
1877// ourselves to play some gnarly ABI tricks just to simplify the calling convention. This is
1878// particularly safe here since this is never called on the critical path - it's only for
1879// testing.
1880void JIT_OPERATION operationExceptionFuzz()
1881{
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +00001882 // This probably "just works" for GCC also, but I haven't tried.
1883#if COMPILER(CLANG)
1884 ExecState* exec = static_cast<ExecState*>(__builtin_frame_address(1));
fpizlo@apple.com8b5ff622014-07-22 18:27:17 +00001885 void* returnPC = __builtin_return_address(0);
1886 doExceptionFuzzing(exec, "JITOperations", returnPC);
fpizlo@apple.com9f1dad42014-07-18 04:34:16 +00001887#endif // COMPILER(CLANG)
1888}
1889
fpizlo@apple.coma398a562014-08-06 21:32:55 +00001890int32_t JIT_OPERATION operationGetEnumerableLength(ExecState* exec, JSCell* baseCell)
1891{
1892 VM& vm = exec->vm();
1893 NativeCallFrameTracer tracer(&vm, exec);
1894 JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
1895 return base->methodTable(vm)->getEnumerableLength(exec, base);
1896}
1897
1898EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
1899{
1900 VM& vm = exec->vm();
1901 NativeCallFrameTracer tracer(&vm, exec);
1902 JSValue baseValue = JSValue::decode(encodedBaseValue);
1903 if (baseValue.isUndefinedOrNull())
1904 return JSValue::encode(jsBoolean(false));
1905
1906 JSObject* base = baseValue.toObject(exec);
1907 return JSValue::encode(jsBoolean(base->hasProperty(exec, asString(propertyName)->toIdentifier(exec))));
1908}
1909
1910EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
1911{
1912 VM& vm = exec->vm();
1913 NativeCallFrameTracer tracer(&vm, exec);
1914 JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
1915 return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
1916}
1917
1918JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState* exec, JSCell* cell, int32_t length)
1919{
1920 VM& vm = exec->vm();
1921 NativeCallFrameTracer tracer(&vm, exec);
1922
1923 JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
1924 ASSERT(length >= 0);
1925
1926 return structurePropertyNameEnumerator(exec, base, static_cast<uint32_t>(length));
1927}
1928
1929JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState* exec, JSCell* baseCell, int32_t length, JSCell* structureEnumeratorCell)
1930{
1931 VM& vm = exec->vm();
1932 NativeCallFrameTracer tracer(&vm, exec);
1933
1934 JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
1935 ASSERT(length >= 0);
1936
1937 return genericPropertyNameEnumerator(exec, base, length, jsCast<JSPropertyNameEnumerator*>(structureEnumeratorCell));
1938}
1939
1940EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
1941{
1942 VM& vm = exec->vm();
1943 NativeCallFrameTracer tracer(&vm, exec);
1944 JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorCell);
1945 JSString* propertyName = enumerator->propertyNameAtIndex(index);
1946 return JSValue::encode(propertyName ? propertyName : jsNull());
1947}
1948
1949JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
1950{
1951 VM& vm = exec->vm();
1952 NativeCallFrameTracer tracer(&vm, exec);
1953 return jsString(exec, Identifier::from(exec, index).string());
1954}
1955
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001956void JIT_OPERATION operationProcessTypeProfilerLog(ExecState* exec)
1957{
commit-queue@webkit.org2ed31ec2014-08-21 01:03:20 +00001958 exec->vm().typeProfilerLog()->processLogEntries(ASCIILiteral("Log Full, called from inside baseline JIT"));
commit-queue@webkit.orgeafc9b32014-08-14 23:59:44 +00001959}
1960
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00001961} // extern "C"
1962
1963// Note: getHostCallReturnValueWithExecState() needs to be placed before the
1964// definition of getHostCallReturnValue() below because the Windows build
1965// requires it.
1966extern "C" EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValueWithExecState(ExecState* exec)
1967{
1968 if (!exec)
1969 return JSValue::encode(JSValue());
1970 return JSValue::encode(exec->vm().hostCallReturnValue);
1971}
1972
1973#if COMPILER(GCC) && CPU(X86_64)
1974asm (
1975".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1976HIDE_SYMBOL(getHostCallReturnValue) "\n"
1977SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
msaboff@apple.comcb9adb02013-11-07 23:45:56 +00001978 "mov %rbp, %rdi\n"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00001979 "jmp " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1980);
1981
1982#elif COMPILER(GCC) && CPU(X86)
1983asm (
1984".text" "\n" \
1985".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
1986HIDE_SYMBOL(getHostCallReturnValue) "\n"
1987SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
msaboff@apple.com95894332014-01-29 19:18:54 +00001988 "push %ebp\n"
1989 "leal -4(%esp), %esp\n"
1990 "push %ebp\n"
mark.lam@apple.comd4454b02014-03-11 04:06:31 +00001991 "call " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
1992 "leal 8(%esp), %esp\n"
1993 "pop %ebp\n"
1994 "ret\n"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00001995);
1996
1997#elif COMPILER(GCC) && CPU(ARM_THUMB2)
1998asm (
1999".text" "\n"
2000".align 2" "\n"
2001".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2002HIDE_SYMBOL(getHostCallReturnValue) "\n"
2003".thumb" "\n"
2004".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n"
2005SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
commit-queue@webkit.orga20a1e82013-11-08 18:25:52 +00002006 "mov r0, r7" "\n"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00002007 "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2008);
2009
2010#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL)
2011asm (
2012".text" "\n"
2013".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2014HIDE_SYMBOL(getHostCallReturnValue) "\n"
2015INLINE_ARM_FUNCTION(getHostCallReturnValue)
2016SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
commit-queue@webkit.orga20a1e82013-11-08 18:25:52 +00002017 "mov r0, r11" "\n"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00002018 "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2019);
2020
dbates@webkit.org98f0de02013-10-15 22:16:39 +00002021#elif CPU(ARM64)
2022asm (
2023".text" "\n"
2024".align 2" "\n"
2025".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2026HIDE_SYMBOL(getHostCallReturnValue) "\n"
2027SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
msaboff@apple.com46627082013-11-19 00:07:53 +00002028 "mov x0, x29" "\n"
dbates@webkit.org98f0de02013-10-15 22:16:39 +00002029 "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2030);
2031
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00002032#elif COMPILER(GCC) && CPU(MIPS)
commit-queue@webkit.orgdee92042014-04-09 21:41:40 +00002033
2034#if WTF_MIPS_PIC
2035#define LOAD_FUNCTION_TO_T9(function) \
2036 ".set noreorder" "\n" \
2037 ".cpload $25" "\n" \
2038 ".set reorder" "\n" \
2039 "la $t9, " LOCAL_REFERENCE(function) "\n"
2040#else
2041#define LOAD_FUNCTION_TO_T9(function) "" "\n"
2042#endif
2043
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00002044asm (
2045".text" "\n"
2046".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2047HIDE_SYMBOL(getHostCallReturnValue) "\n"
2048SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
2049 LOAD_FUNCTION_TO_T9(getHostCallReturnValueWithExecState)
commit-queue@webkit.org9df47ef2013-11-08 18:24:32 +00002050 "move $a0, $fp" "\n"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00002051 "b " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "\n"
2052);
2053
2054#elif COMPILER(GCC) && CPU(SH4)
commit-queue@webkit.orgdee92042014-04-09 21:41:40 +00002055
2056#define SH4_SCRATCH_REGISTER "r11"
2057
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00002058asm (
2059".text" "\n"
2060".globl " SYMBOL_STRING(getHostCallReturnValue) "\n"
2061HIDE_SYMBOL(getHostCallReturnValue) "\n"
2062SYMBOL_STRING(getHostCallReturnValue) ":" "\n"
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00002063 "mov r14, r4" "\n"
2064 "mov.l 2f, " SH4_SCRATCH_REGISTER "\n"
2065 "braf " SH4_SCRATCH_REGISTER "\n"
2066 "nop" "\n"
2067 "1: .balign 4" "\n"
2068 "2: .long " LOCAL_REFERENCE(getHostCallReturnValueWithExecState) "-1b\n"
2069);
2070
2071#elif COMPILER(MSVC) && CPU(X86)
2072extern "C" {
2073 __declspec(naked) EncodedJSValue HOST_CALL_RETURN_VALUE_OPTION getHostCallReturnValue()
2074 {
commit-queue@webkit.orga1af8732013-11-08 17:12:27 +00002075 __asm mov [esp + 4], ebp;
2076 __asm jmp getHostCallReturnValueWithExecState
mark.lam@apple.com9df8b832013-09-26 20:27:14 +00002077 }
2078}
2079#endif
2080
2081} // namespace JSC
2082
commit-queue@webkit.orgac143fb2013-10-09 00:05:49 +00002083#endif // ENABLE(JIT)