]>
Commit | Line | Data |
---|---|---|
81345200 A |
1 | /* |
2 | * Copyright (C) 2011, 2012, 2013, 2014 Apple Inc. All rights reserved. | |
3 | * | |
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 "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" | |
38 | #include "JIT.h" | |
39 | #include "JITStubs.h" | |
40 | #include "JSActivation.h" | |
41 | #include "JSCJSValue.h" | |
42 | #include "JSGlobalObjectFunctions.h" | |
43 | #include "JSNameScope.h" | |
44 | #include "JSPropertyNameIterator.h" | |
45 | #include "JSString.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> | |
55 | ||
56 | namespace JSC { | |
57 | ||
58 | #define BEGIN_NO_SET_PC() \ | |
59 | VM& vm = exec->vm(); \ | |
60 | NativeCallFrameTracer tracer(&vm, exec) | |
61 | ||
62 | #ifndef NDEBUG | |
63 | #define SET_PC_FOR_STUBS() do { \ | |
64 | exec->codeBlock()->bytecodeOffset(pc); \ | |
65 | exec->setCurrentVPC(pc + 1); \ | |
66 | } while (false) | |
67 | #else | |
68 | #define SET_PC_FOR_STUBS() do { \ | |
69 | exec->setCurrentVPC(pc + 1); \ | |
70 | } while (false) | |
71 | #endif | |
72 | ||
73 | #define RETURN_TO_THROW(exec, pc) pc = LLInt::returnToThrow(exec) | |
74 | ||
75 | #define BEGIN() \ | |
76 | BEGIN_NO_SET_PC(); \ | |
77 | SET_PC_FOR_STUBS() | |
78 | ||
79 | #define OP(index) (exec->uncheckedR(pc[index].u.operand)) | |
80 | #define OP_C(index) (exec->r(pc[index].u.operand)) | |
81 | ||
82 | #define RETURN_TWO(first, second) do { \ | |
83 | return encodeResult(first, second); \ | |
84 | } while (false) | |
85 | ||
86 | #define END_IMPL() RETURN_TWO(pc, exec) | |
87 | ||
88 | #define THROW(exceptionToThrow) do { \ | |
89 | vm.throwException(exec, exceptionToThrow); \ | |
90 | RETURN_TO_THROW(exec, pc); \ | |
91 | END_IMPL(); \ | |
92 | } while (false) | |
93 | ||
94 | #define CHECK_EXCEPTION() do { \ | |
95 | if (UNLIKELY(vm.exception())) { \ | |
96 | RETURN_TO_THROW(exec, pc); \ | |
97 | END_IMPL(); \ | |
98 | } \ | |
99 | } while (false) | |
100 | ||
101 | #define END() do { \ | |
102 | CHECK_EXCEPTION(); \ | |
103 | END_IMPL(); \ | |
104 | } while (false) | |
105 | ||
106 | #define BRANCH(opcode, condition) do { \ | |
107 | bool bCondition = (condition); \ | |
108 | CHECK_EXCEPTION(); \ | |
109 | if (bCondition) \ | |
110 | pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \ | |
111 | else \ | |
112 | pc += OPCODE_LENGTH(opcode); \ | |
113 | END_IMPL(); \ | |
114 | } while (false) | |
115 | ||
116 | #define RETURN(value) do { \ | |
117 | JSValue rReturnValue = (value); \ | |
118 | CHECK_EXCEPTION(); \ | |
119 | OP(1) = rReturnValue; \ | |
120 | END_IMPL(); \ | |
121 | } while (false) | |
122 | ||
123 | #define RETURN_PROFILED(opcode, value) do { \ | |
124 | JSValue rpPeturnValue = (value); \ | |
125 | CHECK_EXCEPTION(); \ | |
126 | OP(1) = rpPeturnValue; \ | |
127 | PROFILE_VALUE(opcode, rpPeturnValue); \ | |
128 | END_IMPL(); \ | |
129 | } while (false) | |
130 | ||
131 | #define PROFILE_VALUE(opcode, value) do { \ | |
132 | pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \ | |
133 | JSValue::encode(value); \ | |
134 | } while (false) | |
135 | ||
136 | #define CALL_END_IMPL(exec, callTarget) RETURN_TWO((callTarget), (exec)) | |
137 | ||
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)); \ | |
143 | } while (false) | |
144 | ||
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)); \ | |
150 | } while (false) | |
151 | ||
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); \ | |
158 | } while (false) | |
159 | ||
160 | static CommonSlowPaths::ArityCheckData* setupArityCheckData(VM& vm, int slotsToAdd) | |
161 | { | |
162 | CommonSlowPaths::ArityCheckData* result = vm.arityCheckData.get(); | |
163 | result->paddedStackSpace = slotsToAdd; | |
164 | #if ENABLE(JIT) | |
165 | if (vm.canUseJIT()) { | |
166 | result->thunkToCall = vm.getCTIStub(arityFixup).code().executableAddress(); | |
167 | result->returnPC = vm.arityCheckFailReturnThunks->returnPCFor(vm, slotsToAdd * stackAlignmentRegisters()).executableAddress(); | |
168 | } else | |
169 | #endif | |
170 | { | |
171 | result->thunkToCall = 0; | |
172 | result->returnPC = 0; | |
173 | } | |
174 | return result; | |
175 | } | |
176 | ||
177 | SLOW_PATH_DECL(slow_path_call_arityCheck) | |
178 | { | |
179 | BEGIN(); | |
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); | |
186 | } | |
187 | RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd)); | |
188 | } | |
189 | ||
190 | SLOW_PATH_DECL(slow_path_construct_arityCheck) | |
191 | { | |
192 | BEGIN(); | |
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); | |
199 | } | |
200 | RETURN_TWO(0, setupArityCheckData(vm, slotsToAdd)); | |
201 | } | |
202 | ||
203 | SLOW_PATH_DECL(slow_path_touch_entry) | |
204 | { | |
205 | BEGIN(); | |
206 | exec->codeBlock()->symbolTable()->m_functionEnteredOnce.touch(); | |
207 | END(); | |
208 | } | |
209 | ||
210 | SLOW_PATH_DECL(slow_path_get_callee) | |
211 | { | |
212 | BEGIN(); | |
213 | JSFunction* callee = jsCast<JSFunction*>(exec->callee()); | |
214 | pc[2].u.jsCell.set(exec->vm(), exec->codeBlock()->ownerExecutable(), callee); | |
215 | RETURN(callee); | |
216 | } | |
217 | ||
218 | SLOW_PATH_DECL(slow_path_create_arguments) | |
219 | { | |
220 | BEGIN(); | |
221 | JSValue arguments = JSValue(Arguments::create(vm, exec)); | |
222 | CHECK_EXCEPTION(); | |
223 | exec->uncheckedR(pc[1].u.operand) = arguments; | |
224 | exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[1].u.operand)).offset()) = arguments; | |
225 | END(); | |
226 | } | |
227 | ||
228 | SLOW_PATH_DECL(slow_path_create_this) | |
229 | { | |
230 | BEGIN(); | |
231 | JSFunction* constructor = jsCast<JSFunction*>(OP(2).jsValue().asCell()); | |
232 | ||
233 | #if !ASSERT_DISABLED | |
234 | ConstructData constructData; | |
235 | ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS); | |
236 | #endif | |
237 | ||
238 | size_t inlineCapacity = pc[3].u.operand; | |
239 | Structure* structure = constructor->allocationProfile(exec, inlineCapacity)->structure(); | |
240 | RETURN(constructEmptyObject(exec, structure)); | |
241 | } | |
242 | ||
243 | SLOW_PATH_DECL(slow_path_to_this) | |
244 | { | |
245 | BEGIN(); | |
246 | JSValue v1 = OP(1).jsValue(); | |
247 | if (v1.isCell()) | |
248 | pc[2].u.structure.set(vm, exec->codeBlock()->ownerExecutable(), v1.asCell()->structure(vm)); | |
249 | else | |
250 | pc[2].u.structure.clear(); | |
251 | RETURN(v1.toThis(exec, exec->codeBlock()->isStrictMode() ? StrictMode : NotStrictMode)); | |
252 | } | |
253 | ||
254 | SLOW_PATH_DECL(slow_path_captured_mov) | |
255 | { | |
256 | BEGIN(); | |
257 | JSValue value = OP_C(2).jsValue(); | |
258 | if (VariableWatchpointSet* set = pc[3].u.watchpointSet) | |
259 | set->notifyWrite(vm, value); | |
260 | RETURN(value); | |
261 | } | |
262 | ||
263 | SLOW_PATH_DECL(slow_path_new_captured_func) | |
264 | { | |
265 | BEGIN(); | |
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); | |
271 | RETURN(value); | |
272 | } | |
273 | ||
274 | SLOW_PATH_DECL(slow_path_not) | |
275 | { | |
276 | BEGIN(); | |
277 | RETURN(jsBoolean(!OP_C(2).jsValue().toBoolean(exec))); | |
278 | } | |
279 | ||
280 | SLOW_PATH_DECL(slow_path_eq) | |
281 | { | |
282 | BEGIN(); | |
283 | RETURN(jsBoolean(JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue()))); | |
284 | } | |
285 | ||
286 | SLOW_PATH_DECL(slow_path_neq) | |
287 | { | |
288 | BEGIN(); | |
289 | RETURN(jsBoolean(!JSValue::equal(exec, OP_C(2).jsValue(), OP_C(3).jsValue()))); | |
290 | } | |
291 | ||
292 | SLOW_PATH_DECL(slow_path_stricteq) | |
293 | { | |
294 | BEGIN(); | |
295 | RETURN(jsBoolean(JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue()))); | |
296 | } | |
297 | ||
298 | SLOW_PATH_DECL(slow_path_nstricteq) | |
299 | { | |
300 | BEGIN(); | |
301 | RETURN(jsBoolean(!JSValue::strictEqual(exec, OP_C(2).jsValue(), OP_C(3).jsValue()))); | |
302 | } | |
303 | ||
304 | SLOW_PATH_DECL(slow_path_less) | |
305 | { | |
306 | BEGIN(); | |
307 | RETURN(jsBoolean(jsLess<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue()))); | |
308 | } | |
309 | ||
310 | SLOW_PATH_DECL(slow_path_lesseq) | |
311 | { | |
312 | BEGIN(); | |
313 | RETURN(jsBoolean(jsLessEq<true>(exec, OP_C(2).jsValue(), OP_C(3).jsValue()))); | |
314 | } | |
315 | ||
316 | SLOW_PATH_DECL(slow_path_greater) | |
317 | { | |
318 | BEGIN(); | |
319 | RETURN(jsBoolean(jsLess<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue()))); | |
320 | } | |
321 | ||
322 | SLOW_PATH_DECL(slow_path_greatereq) | |
323 | { | |
324 | BEGIN(); | |
325 | RETURN(jsBoolean(jsLessEq<false>(exec, OP_C(3).jsValue(), OP_C(2).jsValue()))); | |
326 | } | |
327 | ||
328 | SLOW_PATH_DECL(slow_path_inc) | |
329 | { | |
330 | BEGIN(); | |
331 | RETURN(jsNumber(OP(1).jsValue().toNumber(exec) + 1)); | |
332 | } | |
333 | ||
334 | SLOW_PATH_DECL(slow_path_dec) | |
335 | { | |
336 | BEGIN(); | |
337 | RETURN(jsNumber(OP(1).jsValue().toNumber(exec) - 1)); | |
338 | } | |
339 | ||
340 | SLOW_PATH_DECL(slow_path_to_number) | |
341 | { | |
342 | BEGIN(); | |
343 | RETURN(jsNumber(OP_C(2).jsValue().toNumber(exec))); | |
344 | } | |
345 | ||
346 | SLOW_PATH_DECL(slow_path_negate) | |
347 | { | |
348 | BEGIN(); | |
349 | RETURN(jsNumber(-OP_C(2).jsValue().toNumber(exec))); | |
350 | } | |
351 | ||
352 | SLOW_PATH_DECL(slow_path_add) | |
353 | { | |
354 | BEGIN(); | |
355 | JSValue v1 = OP_C(2).jsValue(); | |
356 | JSValue v2 = OP_C(3).jsValue(); | |
357 | ||
358 | if (v1.isString() && !v2.isObject()) | |
359 | RETURN(jsString(exec, asString(v1), v2.toString(exec))); | |
360 | ||
361 | if (v1.isNumber() && v2.isNumber()) | |
362 | RETURN(jsNumber(v1.asNumber() + v2.asNumber())); | |
363 | ||
364 | RETURN(jsAddSlowCase(exec, v1, v2)); | |
365 | } | |
366 | ||
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.) | |
370 | ||
371 | SLOW_PATH_DECL(slow_path_mul) | |
372 | { | |
373 | BEGIN(); | |
374 | double a = OP_C(2).jsValue().toNumber(exec); | |
375 | double b = OP_C(3).jsValue().toNumber(exec); | |
376 | RETURN(jsNumber(a * b)); | |
377 | } | |
378 | ||
379 | SLOW_PATH_DECL(slow_path_sub) | |
380 | { | |
381 | BEGIN(); | |
382 | double a = OP_C(2).jsValue().toNumber(exec); | |
383 | double b = OP_C(3).jsValue().toNumber(exec); | |
384 | RETURN(jsNumber(a - b)); | |
385 | } | |
386 | ||
387 | SLOW_PATH_DECL(slow_path_div) | |
388 | { | |
389 | BEGIN(); | |
390 | double a = OP_C(2).jsValue().toNumber(exec); | |
391 | double b = OP_C(3).jsValue().toNumber(exec); | |
392 | RETURN(jsNumber(a / b)); | |
393 | } | |
394 | ||
395 | SLOW_PATH_DECL(slow_path_mod) | |
396 | { | |
397 | BEGIN(); | |
398 | double a = OP_C(2).jsValue().toNumber(exec); | |
399 | double b = OP_C(3).jsValue().toNumber(exec); | |
400 | RETURN(jsNumber(fmod(a, b))); | |
401 | } | |
402 | ||
403 | SLOW_PATH_DECL(slow_path_lshift) | |
404 | { | |
405 | BEGIN(); | |
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))); | |
409 | } | |
410 | ||
411 | SLOW_PATH_DECL(slow_path_rshift) | |
412 | { | |
413 | BEGIN(); | |
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))); | |
417 | } | |
418 | ||
419 | SLOW_PATH_DECL(slow_path_urshift) | |
420 | { | |
421 | BEGIN(); | |
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)))); | |
425 | } | |
426 | ||
427 | SLOW_PATH_DECL(slow_path_unsigned) | |
428 | { | |
429 | BEGIN(); | |
430 | uint32_t a = OP_C(2).jsValue().toUInt32(exec); | |
431 | RETURN(jsNumber(a)); | |
432 | } | |
433 | ||
434 | SLOW_PATH_DECL(slow_path_bitand) | |
435 | { | |
436 | BEGIN(); | |
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)); | |
440 | } | |
441 | ||
442 | SLOW_PATH_DECL(slow_path_bitor) | |
443 | { | |
444 | BEGIN(); | |
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)); | |
448 | } | |
449 | ||
450 | SLOW_PATH_DECL(slow_path_bitxor) | |
451 | { | |
452 | BEGIN(); | |
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)); | |
456 | } | |
457 | ||
458 | SLOW_PATH_DECL(slow_path_typeof) | |
459 | { | |
460 | BEGIN(); | |
461 | RETURN(jsTypeStringForValue(exec, OP_C(2).jsValue())); | |
462 | } | |
463 | ||
464 | SLOW_PATH_DECL(slow_path_is_object) | |
465 | { | |
466 | BEGIN(); | |
467 | RETURN(jsBoolean(jsIsObjectType(exec, OP_C(2).jsValue()))); | |
468 | } | |
469 | ||
470 | SLOW_PATH_DECL(slow_path_is_function) | |
471 | { | |
472 | BEGIN(); | |
473 | RETURN(jsBoolean(jsIsFunctionType(OP_C(2).jsValue()))); | |
474 | } | |
475 | ||
476 | SLOW_PATH_DECL(slow_path_in) | |
477 | { | |
478 | BEGIN(); | |
479 | RETURN(jsBoolean(CommonSlowPaths::opIn(exec, OP_C(2).jsValue(), OP_C(3).jsValue()))); | |
480 | } | |
481 | ||
482 | SLOW_PATH_DECL(slow_path_del_by_val) | |
483 | { | |
484 | BEGIN(); | |
485 | JSValue baseValue = OP_C(2).jsValue(); | |
486 | JSObject* baseObject = baseValue.toObject(exec); | |
487 | ||
488 | JSValue subscript = OP_C(3).jsValue(); | |
489 | ||
490 | bool couldDelete; | |
491 | ||
492 | uint32_t i; | |
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()); | |
497 | else { | |
498 | CHECK_EXCEPTION(); | |
499 | Identifier property(exec, subscript.toString(exec)->value(exec)); | |
500 | CHECK_EXCEPTION(); | |
501 | couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property); | |
502 | } | |
503 | ||
504 | if (!couldDelete && exec->codeBlock()->isStrictMode()) | |
505 | THROW(createTypeError(exec, "Unable to delete property.")); | |
506 | ||
507 | RETURN(jsBoolean(couldDelete)); | |
508 | } | |
509 | ||
510 | SLOW_PATH_DECL(slow_path_strcat) | |
511 | { | |
512 | BEGIN(); | |
513 | RETURN(jsStringFromRegisterArray(exec, &OP(2), pc[3].u.operand)); | |
514 | } | |
515 | ||
516 | SLOW_PATH_DECL(slow_path_to_primitive) | |
517 | { | |
518 | BEGIN(); | |
519 | RETURN(OP_C(2).jsValue().toPrimitive(exec)); | |
520 | } | |
521 | ||
522 | SLOW_PATH_DECL(slow_path_enter) | |
523 | { | |
524 | BEGIN(); | |
525 | ScriptExecutable* ownerExecutable = exec->codeBlock()->ownerExecutable(); | |
526 | Heap::heap(ownerExecutable)->writeBarrier(ownerExecutable); | |
527 | END(); | |
528 | } | |
529 | ||
530 | } // namespace JSC |