2 * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "CommonSlowPaths.h"
28 #include "Arguments.h"
29 #include "ArityCheckFailReturnThunks.h"
30 #include "ArrayConstructor.h"
31 #include "CallFrame.h"
32 #include "CodeProfiling.h"
33 #include "CommonSlowPathsExceptions.h"
34 #include "ErrorHandlingScope.h"
35 #include "GetterSetter.h"
36 #include "HostCallReturnValue.h"
37 #include "Interpreter.h"
40 #include "JSActivation.h"
41 #include "JSCJSValue.h"
42 #include "JSGlobalObjectFunctions.h"
43 #include "JSNameScope.h"
44 #include "JSPropertyNameIterator.h"
46 #include "JSWithScope.h"
47 #include "LLIntCommon.h"
48 #include "LLIntExceptions.h"
49 #include "LowLevelInterpreter.h"
50 #include "ObjectConstructor.h"
51 #include "JSCInlines.h"
52 #include "StructureRareDataInlines.h"
53 #include "VariableWatchpointSetInlines.h"
54 #include <wtf/StringPrintStream.h>
58 #define BEGIN_NO_SET_PC() \
59 VM& vm = exec->vm(); \
60 NativeCallFrameTracer tracer(&vm, exec)
63 #define SET_PC_FOR_STUBS() do { \
64 exec->codeBlock()->bytecodeOffset(pc); \
65 exec->setCurrentVPC(pc + 1); \
68 #define SET_PC_FOR_STUBS() do { \
69 exec->setCurrentVPC(pc + 1); \
73 #define RETURN_TO_THROW(exec, pc) pc = LLInt::returnToThrow(exec)
79 #define OP(index) (exec->uncheckedR(pc[index].u.operand))
80 #define OP_C(index) (exec->r(pc[index].u.operand))
82 #define RETURN_TWO(first, second) do { \
83 return encodeResult(first, second); \
86 #define END_IMPL() RETURN_TWO(pc, exec)
88 #define THROW(exceptionToThrow) do { \
89 vm.throwException(exec, exceptionToThrow); \
90 RETURN_TO_THROW(exec, pc); \
94 #define CHECK_EXCEPTION() do { \
95 if (UNLIKELY(vm.exception())) { \
96 RETURN_TO_THROW(exec, pc); \
106 #define BRANCH(opcode, condition) do { \
107 bool bCondition = (condition); \
110 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \
112 pc += OPCODE_LENGTH(opcode); \
116 #define RETURN(value) do { \
117 JSValue rReturnValue = (value); \
119 OP(1) = rReturnValue; \
123 #define RETURN_PROFILED(opcode, value) do { \
124 JSValue rpPeturnValue = (value); \
126 OP(1) = rpPeturnValue; \
127 PROFILE_VALUE(opcode, rpPeturnValue); \
131 #define PROFILE_VALUE(opcode, value) do { \
132 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \
133 JSValue::encode(value); \
136 #define CALL_END_IMPL(exec, callTarget) RETURN_TWO((callTarget), (exec))
138 #define CALL_THROW(exec, pc, exceptionToThrow) do { \
139 ExecState* ctExec = (exec); \
140 Instruction* ctPC = (pc); \
141 vm.throwException(exec, exceptionToThrow); \
142 CALL_END_IMPL(ctExec, LLInt::callToThrow(ctExec)); \
145 #define CALL_CHECK_EXCEPTION(exec, pc) do { \
146 ExecState* cceExec = (exec); \
147 Instruction* ccePC = (pc); \
148 if (UNLIKELY(vm.exception())) \
149 CALL_END_IMPL(cceExec, LLInt::callToThrow(cceExec)); \
152 #define CALL_RETURN(exec, pc, callTarget) do { \
153 ExecState* crExec = (exec); \
154 Instruction* crPC = (pc); \
155 void* crCallTarget = (callTarget); \
156 CALL_CHECK_EXCEPTION(crExec->callerFrame(), crPC); \
157 CALL_END_IMPL(crExec, crCallTarget); \
160 static CommonSlowPaths::ArityCheckData
* setupArityCheckData(VM
& vm
, int slotsToAdd
)
162 CommonSlowPaths::ArityCheckData
* result
= vm
.arityCheckData
.get();
163 result
->paddedStackSpace
= slotsToAdd
;
165 if (vm
.canUseJIT()) {
166 result
->thunkToCall
= vm
.getCTIStub(arityFixup
).code().executableAddress();
167 result
->returnPC
= vm
.arityCheckFailReturnThunks
->returnPCFor(vm
, slotsToAdd
* stackAlignmentRegisters()).executableAddress();
171 result
->thunkToCall
= 0;
172 result
->returnPC
= 0;
177 SLOW_PATH_DECL(slow_path_call_arityCheck
)
180 int slotsToAdd
= CommonSlowPaths::arityCheckFor(exec
, &vm
.interpreter
->stack(), CodeForCall
);
181 if (slotsToAdd
< 0) {
182 exec
= exec
->callerFrame();
183 ErrorHandlingScope
errorScope(exec
->vm());
184 CommonSlowPaths::interpreterThrowInCaller(exec
, createStackOverflowError(exec
));
185 RETURN_TWO(bitwise_cast
<void*>(static_cast<uintptr_t>(1)), exec
);
187 RETURN_TWO(0, setupArityCheckData(vm
, slotsToAdd
));
190 SLOW_PATH_DECL(slow_path_construct_arityCheck
)
193 int slotsToAdd
= CommonSlowPaths::arityCheckFor(exec
, &vm
.interpreter
->stack(), CodeForConstruct
);
194 if (slotsToAdd
< 0) {
195 exec
= exec
->callerFrame();
196 ErrorHandlingScope
errorScope(exec
->vm());
197 CommonSlowPaths::interpreterThrowInCaller(exec
, createStackOverflowError(exec
));
198 RETURN_TWO(bitwise_cast
<void*>(static_cast<uintptr_t>(1)), exec
);
200 RETURN_TWO(0, setupArityCheckData(vm
, slotsToAdd
));
203 SLOW_PATH_DECL(slow_path_touch_entry
)
206 exec
->codeBlock()->symbolTable()->m_functionEnteredOnce
.touch();
210 SLOW_PATH_DECL(slow_path_get_callee
)
213 JSFunction
* callee
= jsCast
<JSFunction
*>(exec
->callee());
214 pc
[2].u
.jsCell
.set(exec
->vm(), exec
->codeBlock()->ownerExecutable(), callee
);
218 SLOW_PATH_DECL(slow_path_create_arguments
)
221 JSValue arguments
= JSValue(Arguments::create(vm
, exec
));
223 exec
->uncheckedR(pc
[1].u
.operand
) = arguments
;
224 exec
->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc
[1].u
.operand
)).offset()) = arguments
;
228 SLOW_PATH_DECL(slow_path_create_this
)
231 JSFunction
* constructor
= jsCast
<JSFunction
*>(OP(2).jsValue().asCell());
234 ConstructData constructData
;
235 ASSERT(constructor
->methodTable()->getConstructData(constructor
, constructData
) == ConstructTypeJS
);
238 size_t inlineCapacity
= pc
[3].u
.operand
;
239 Structure
* structure
= constructor
->allocationProfile(exec
, inlineCapacity
)->structure();
240 RETURN(constructEmptyObject(exec
, structure
));
243 SLOW_PATH_DECL(slow_path_to_this
)
246 JSValue v1
= OP(1).jsValue();
248 pc
[2].u
.structure
.set(vm
, exec
->codeBlock()->ownerExecutable(), v1
.asCell()->structure(vm
));
250 pc
[2].u
.structure
.clear();
251 RETURN(v1
.toThis(exec
, exec
->codeBlock()->isStrictMode() ? StrictMode
: NotStrictMode
));
254 SLOW_PATH_DECL(slow_path_captured_mov
)
257 JSValue value
= OP_C(2).jsValue();
258 if (VariableWatchpointSet
* set
= pc
[3].u
.watchpointSet
)
259 set
->notifyWrite(vm
, value
);
263 SLOW_PATH_DECL(slow_path_new_captured_func
)
266 CodeBlock
* codeBlock
= exec
->codeBlock();
267 ASSERT(codeBlock
->codeType() != FunctionCode
|| !codeBlock
->needsActivation() || exec
->hasActivation());
268 JSValue value
= JSFunction::create(vm
, codeBlock
->functionDecl(pc
[2].u
.operand
), exec
->scope());
269 if (VariableWatchpointSet
* set
= pc
[3].u
.watchpointSet
)
270 set
->notifyWrite(vm
, value
);
274 SLOW_PATH_DECL(slow_path_not
)
277 RETURN(jsBoolean(!OP_C(2).jsValue().toBoolean(exec
)));
280 SLOW_PATH_DECL(slow_path_eq
)
283 RETURN(jsBoolean(JSValue::equal(exec
, OP_C(2).jsValue(), OP_C(3).jsValue())));
286 SLOW_PATH_DECL(slow_path_neq
)
289 RETURN(jsBoolean(!JSValue::equal(exec
, OP_C(2).jsValue(), OP_C(3).jsValue())));
292 SLOW_PATH_DECL(slow_path_stricteq
)
295 RETURN(jsBoolean(JSValue::strictEqual(exec
, OP_C(2).jsValue(), OP_C(3).jsValue())));
298 SLOW_PATH_DECL(slow_path_nstricteq
)
301 RETURN(jsBoolean(!JSValue::strictEqual(exec
, OP_C(2).jsValue(), OP_C(3).jsValue())));
304 SLOW_PATH_DECL(slow_path_less
)
307 RETURN(jsBoolean(jsLess
<true>(exec
, OP_C(2).jsValue(), OP_C(3).jsValue())));
310 SLOW_PATH_DECL(slow_path_lesseq
)
313 RETURN(jsBoolean(jsLessEq
<true>(exec
, OP_C(2).jsValue(), OP_C(3).jsValue())));
316 SLOW_PATH_DECL(slow_path_greater
)
319 RETURN(jsBoolean(jsLess
<false>(exec
, OP_C(3).jsValue(), OP_C(2).jsValue())));
322 SLOW_PATH_DECL(slow_path_greatereq
)
325 RETURN(jsBoolean(jsLessEq
<false>(exec
, OP_C(3).jsValue(), OP_C(2).jsValue())));
328 SLOW_PATH_DECL(slow_path_inc
)
331 RETURN(jsNumber(OP(1).jsValue().toNumber(exec
) + 1));
334 SLOW_PATH_DECL(slow_path_dec
)
337 RETURN(jsNumber(OP(1).jsValue().toNumber(exec
) - 1));
340 SLOW_PATH_DECL(slow_path_to_number
)
343 RETURN(jsNumber(OP_C(2).jsValue().toNumber(exec
)));
346 SLOW_PATH_DECL(slow_path_negate
)
349 RETURN(jsNumber(-OP_C(2).jsValue().toNumber(exec
)));
352 SLOW_PATH_DECL(slow_path_add
)
355 JSValue v1
= OP_C(2).jsValue();
356 JSValue v2
= OP_C(3).jsValue();
358 if (v1
.isString() && !v2
.isObject())
359 RETURN(jsString(exec
, asString(v1
), v2
.toString(exec
)));
361 if (v1
.isNumber() && v2
.isNumber())
362 RETURN(jsNumber(v1
.asNumber() + v2
.asNumber()));
364 RETURN(jsAddSlowCase(exec
, v1
, v2
));
367 // The following arithmetic and bitwise operations need to be sure to run
368 // toNumber() on their operands in order. (A call to toNumber() is idempotent
369 // if an exception is already set on the ExecState.)
371 SLOW_PATH_DECL(slow_path_mul
)
374 double a
= OP_C(2).jsValue().toNumber(exec
);
375 double b
= OP_C(3).jsValue().toNumber(exec
);
376 RETURN(jsNumber(a
* b
));
379 SLOW_PATH_DECL(slow_path_sub
)
382 double a
= OP_C(2).jsValue().toNumber(exec
);
383 double b
= OP_C(3).jsValue().toNumber(exec
);
384 RETURN(jsNumber(a
- b
));
387 SLOW_PATH_DECL(slow_path_div
)
390 double a
= OP_C(2).jsValue().toNumber(exec
);
391 double b
= OP_C(3).jsValue().toNumber(exec
);
392 RETURN(jsNumber(a
/ b
));
395 SLOW_PATH_DECL(slow_path_mod
)
398 double a
= OP_C(2).jsValue().toNumber(exec
);
399 double b
= OP_C(3).jsValue().toNumber(exec
);
400 RETURN(jsNumber(fmod(a
, b
)));
403 SLOW_PATH_DECL(slow_path_lshift
)
406 int32_t a
= OP_C(2).jsValue().toInt32(exec
);
407 uint32_t b
= OP_C(3).jsValue().toUInt32(exec
);
408 RETURN(jsNumber(a
<< (b
& 31)));
411 SLOW_PATH_DECL(slow_path_rshift
)
414 int32_t a
= OP_C(2).jsValue().toInt32(exec
);
415 uint32_t b
= OP_C(3).jsValue().toUInt32(exec
);
416 RETURN(jsNumber(a
>> (b
& 31)));
419 SLOW_PATH_DECL(slow_path_urshift
)
422 uint32_t a
= OP_C(2).jsValue().toUInt32(exec
);
423 uint32_t b
= OP_C(3).jsValue().toUInt32(exec
);
424 RETURN(jsNumber(static_cast<int32_t>(a
>> (b
& 31))));
427 SLOW_PATH_DECL(slow_path_unsigned
)
430 uint32_t a
= OP_C(2).jsValue().toUInt32(exec
);
434 SLOW_PATH_DECL(slow_path_bitand
)
437 int32_t a
= OP_C(2).jsValue().toInt32(exec
);
438 int32_t b
= OP_C(3).jsValue().toInt32(exec
);
439 RETURN(jsNumber(a
& b
));
442 SLOW_PATH_DECL(slow_path_bitor
)
445 int32_t a
= OP_C(2).jsValue().toInt32(exec
);
446 int32_t b
= OP_C(3).jsValue().toInt32(exec
);
447 RETURN(jsNumber(a
| b
));
450 SLOW_PATH_DECL(slow_path_bitxor
)
453 int32_t a
= OP_C(2).jsValue().toInt32(exec
);
454 int32_t b
= OP_C(3).jsValue().toInt32(exec
);
455 RETURN(jsNumber(a
^ b
));
458 SLOW_PATH_DECL(slow_path_typeof
)
461 RETURN(jsTypeStringForValue(exec
, OP_C(2).jsValue()));
464 SLOW_PATH_DECL(slow_path_is_object
)
467 RETURN(jsBoolean(jsIsObjectType(exec
, OP_C(2).jsValue())));
470 SLOW_PATH_DECL(slow_path_is_function
)
473 RETURN(jsBoolean(jsIsFunctionType(OP_C(2).jsValue())));
476 SLOW_PATH_DECL(slow_path_in
)
479 RETURN(jsBoolean(CommonSlowPaths::opIn(exec
, OP_C(2).jsValue(), OP_C(3).jsValue())));
482 SLOW_PATH_DECL(slow_path_del_by_val
)
485 JSValue baseValue
= OP_C(2).jsValue();
486 JSObject
* baseObject
= baseValue
.toObject(exec
);
488 JSValue subscript
= OP_C(3).jsValue();
493 if (subscript
.getUInt32(i
))
494 couldDelete
= baseObject
->methodTable()->deletePropertyByIndex(baseObject
, exec
, i
);
495 else if (isName(subscript
))
496 couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, jsCast
<NameInstance
*>(subscript
.asCell())->privateName());
499 Identifier
property(exec
, subscript
.toString(exec
)->value(exec
));
501 couldDelete
= baseObject
->methodTable()->deleteProperty(baseObject
, exec
, property
);
504 if (!couldDelete
&& exec
->codeBlock()->isStrictMode())
505 THROW(createTypeError(exec
, "Unable to delete property."));
507 RETURN(jsBoolean(couldDelete
));
510 SLOW_PATH_DECL(slow_path_strcat
)
513 RETURN(jsStringFromRegisterArray(exec
, &OP(2), pc
[3].u
.operand
));
516 SLOW_PATH_DECL(slow_path_to_primitive
)
519 RETURN(OP_C(2).jsValue().toPrimitive(exec
));
522 SLOW_PATH_DECL(slow_path_enter
)
525 ScriptExecutable
* ownerExecutable
= exec
->codeBlock()->ownerExecutable();
526 Heap::heap(ownerExecutable
)->writeBarrier(ownerExecutable
);