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 "LLIntSlowPaths.h" 28#include "Arguments.h" 29#include "ArrayConstructor.h" 30#include "CallFrame.h" 31#include "CommonSlowPaths.h" 32#include "CommonSlowPathsExceptions.h" 33#include "ErrorHandlingScope.h" 34#include "GetterSetter.h" 35#include "HostCallReturnValue.h" 36#include "Interpreter.h" 37#include "JIT.h" 38#include "JITExceptions.h" 39#include "JSActivation.h" 40#include "JSCJSValue.h" 41#include "JSGlobalObjectFunctions.h" 42#include "JSNameScope.h" 43#include "JSPropertyNameIterator.h" 44#include "JSStackInlines.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 "ProtoCallFrame.h" 53#include "StructureRareDataInlines.h" 54#include <wtf/StringPrintStream.h> 55 56namespace JSC { namespace LLInt { 57 58#define LLINT_BEGIN_NO_SET_PC() \ 59 VM& vm = exec->vm(); \ 60 NativeCallFrameTracer tracer(&vm, exec) 61 62#ifndef NDEBUG 63#define LLINT_SET_PC_FOR_STUBS() do { \ 64 exec->codeBlock()->bytecodeOffset(pc); \ 65 exec->setCurrentVPC(pc + 1); \ 66 } while (false) 67#else 68#define LLINT_SET_PC_FOR_STUBS() do { \ 69 exec->setCurrentVPC(pc + 1); \ 70 } while (false) 71#endif 72 73#define LLINT_BEGIN() \ 74 LLINT_BEGIN_NO_SET_PC(); \ 75 LLINT_SET_PC_FOR_STUBS() 76 77#define LLINT_OP(index) (exec->uncheckedR(pc[index].u.operand)) 78#define LLINT_OP_C(index) (exec->r(pc[index].u.operand)) 79 80#define LLINT_RETURN_TWO(first, second) do { \ 81 return encodeResult(first, second); \ 82 } while (false) 83 84#define LLINT_END_IMPL() LLINT_RETURN_TWO(pc, 0) 85 86#define LLINT_THROW(exceptionToThrow) do { \ 87 vm.throwException(exec, exceptionToThrow); \ 88 pc = returnToThrow(exec); \ 89 LLINT_END_IMPL(); \ 90 } while (false) 91 92#define LLINT_CHECK_EXCEPTION() do { \ 93 if (UNLIKELY(vm.exception())) { \ 94 pc = returnToThrow(exec); \ 95 LLINT_END_IMPL(); \ 96 } \ 97 } while (false) 98 99#define LLINT_END() do { \ 100 LLINT_CHECK_EXCEPTION(); \ 101 LLINT_END_IMPL(); \ 102 } while (false) 103 104#define LLINT_BRANCH(opcode, condition) do { \ 105 bool __b_condition = (condition); \ 106 LLINT_CHECK_EXCEPTION(); \ 107 if (__b_condition) \ 108 pc += pc[OPCODE_LENGTH(opcode) - 1].u.operand; \ 109 else \ 110 pc += OPCODE_LENGTH(opcode); \ 111 LLINT_END_IMPL(); \ 112 } while (false) 113 114#define LLINT_RETURN(value) do { \ 115 JSValue __r_returnValue = (value); \ 116 LLINT_CHECK_EXCEPTION(); \ 117 LLINT_OP(1) = __r_returnValue; \ 118 LLINT_END_IMPL(); \ 119 } while (false) 120 121#define LLINT_RETURN_WITH_PC_ADJUSTMENT(value, pcAdjustment) do { \ 122 JSValue __r_returnValue = (value); \ 123 LLINT_CHECK_EXCEPTION(); \ 124 LLINT_OP(1) = __r_returnValue; \ 125 pc += (pcAdjustment); \ 126 LLINT_END_IMPL(); \ 127 } while (false) 128 129#define LLINT_RETURN_PROFILED(opcode, value) do { \ 130 JSValue __rp_returnValue = (value); \ 131 LLINT_CHECK_EXCEPTION(); \ 132 LLINT_OP(1) = __rp_returnValue; \ 133 LLINT_PROFILE_VALUE(opcode, __rp_returnValue); \ 134 LLINT_END_IMPL(); \ 135 } while (false) 136 137#define LLINT_PROFILE_VALUE(opcode, value) do { \ 138 pc[OPCODE_LENGTH(opcode) - 1].u.profile->m_buckets[0] = \ 139 JSValue::encode(value); \ 140 } while (false) 141 142#define LLINT_CALL_END_IMPL(exec, callTarget) LLINT_RETURN_TWO((callTarget), (exec)) 143 144#define LLINT_CALL_THROW(exec, exceptionToThrow) do { \ 145 ExecState* __ct_exec = (exec); \ 146 vm.throwException(__ct_exec, exceptionToThrow); \ 147 LLINT_CALL_END_IMPL(0, callToThrow(__ct_exec)); \ 148 } while (false) 149 150#define LLINT_CALL_CHECK_EXCEPTION(exec) do { \ 151 ExecState* __cce_exec = (exec); \ 152 if (UNLIKELY(vm.exception())) \ 153 LLINT_CALL_END_IMPL(0, callToThrow(__cce_exec)); \ 154 } while (false) 155 156#define LLINT_CALL_RETURN(exec, callTarget) do { \ 157 ExecState* __cr_exec = (exec); \ 158 void* __cr_callTarget = (callTarget); \ 159 LLINT_CALL_CHECK_EXCEPTION(__cr_exec); \ 160 LLINT_CALL_END_IMPL(__cr_exec, __cr_callTarget); \ 161 } while (false) 162 163#define LLINT_RETURN_CALLEE_FRAME(execCallee) do { \ 164 ExecState* __rcf_exec = (execCallee); \ 165 LLINT_RETURN_TWO(pc, __rcf_exec); \ 166 } while (false) 167 168 169extern "C" SlowPathReturnType llint_trace_operand(ExecState* exec, Instruction* pc, int fromWhere, int operand) 170{ 171 LLINT_BEGIN(); 172 dataLogF("%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d\n", 173 exec->codeBlock(), 174 exec, 175 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()), 176 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode), 177 fromWhere, 178 operand, 179 pc[operand].u.operand); 180 LLINT_END(); 181} 182 183extern "C" SlowPathReturnType llint_trace_value(ExecState* exec, Instruction* pc, int fromWhere, int operand) 184{ 185 JSValue value = LLINT_OP_C(operand).jsValue(); 186 union { 187 struct { 188 uint32_t tag; 189 uint32_t payload; 190 } bits; 191 EncodedJSValue asValue; 192 } u; 193 u.asValue = JSValue::encode(value); 194 dataLogF( 195 "%p / %p: executing bc#%zu, op#%u: Trace(%d): %d: %d: %08x:%08x: %s\n", 196 exec->codeBlock(), 197 exec, 198 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()), 199 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode), 200 fromWhere, 201 operand, 202 pc[operand].u.operand, 203 u.bits.tag, 204 u.bits.payload, 205 toCString(value).data()); 206 LLINT_END_IMPL(); 207} 208 209LLINT_SLOW_PATH_DECL(trace_prologue) 210{ 211 dataLogF("%p / %p: in prologue.\n", exec->codeBlock(), exec); 212 LLINT_END_IMPL(); 213} 214 215static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind) 216{ 217 JSFunction* callee = jsCast<JSFunction*>(exec->callee()); 218 FunctionExecutable* executable = callee->jsExecutable(); 219 CodeBlock* codeBlock = executable->codeBlockFor(kind); 220 dataLogF("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n", 221 codeBlock, exec, comment, callee, executable, 222 codeBlock->m_numVars, codeBlock->numParameters(), codeBlock->m_numCalleeRegisters, 223 exec->callerFrame()); 224} 225 226LLINT_SLOW_PATH_DECL(trace_prologue_function_for_call) 227{ 228 traceFunctionPrologue(exec, "call prologue", CodeForCall); 229 LLINT_END_IMPL(); 230} 231 232LLINT_SLOW_PATH_DECL(trace_prologue_function_for_construct) 233{ 234 traceFunctionPrologue(exec, "construct prologue", CodeForConstruct); 235 LLINT_END_IMPL(); 236} 237 238LLINT_SLOW_PATH_DECL(trace_arityCheck_for_call) 239{ 240 traceFunctionPrologue(exec, "call arity check", CodeForCall); 241 LLINT_END_IMPL(); 242} 243 244LLINT_SLOW_PATH_DECL(trace_arityCheck_for_construct) 245{ 246 traceFunctionPrologue(exec, "construct arity check", CodeForConstruct); 247 LLINT_END_IMPL(); 248} 249 250LLINT_SLOW_PATH_DECL(trace) 251{ 252 dataLogF("%p / %p: executing bc#%zu, %s, scope %p, pc = %p\n", 253 exec->codeBlock(), 254 exec, 255 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()), 256 opcodeNames[exec->vm().interpreter->getOpcodeID(pc[0].u.opcode)], 257 exec->scope(), pc); 258 if (exec->vm().interpreter->getOpcodeID(pc[0].u.opcode) == op_enter) { 259 dataLogF("Frame will eventually return to %p\n", exec->returnPC().value()); 260 *bitwise_cast<volatile char*>(exec->returnPC().value()); 261 } 262 if (exec->vm().interpreter->getOpcodeID(pc[0].u.opcode) == op_ret) { 263 dataLogF("Will be returning to %p\n", exec->returnPC().value()); 264 dataLogF("The new cfr will be %p\n", exec->callerFrame()); 265 } 266 LLINT_END_IMPL(); 267} 268 269LLINT_SLOW_PATH_DECL(special_trace) 270{ 271 dataLogF("%p / %p: executing special case bc#%zu, op#%u, return PC is %p\n", 272 exec->codeBlock(), 273 exec, 274 static_cast<intptr_t>(pc - exec->codeBlock()->instructions().begin()), 275 exec->vm().interpreter->getOpcodeID(pc[0].u.opcode), 276 exec->returnPC().value()); 277 LLINT_END_IMPL(); 278} 279 280enum EntryKind { Prologue, ArityCheck }; 281 282#if ENABLE(JIT) 283inline bool shouldJIT(ExecState* exec) 284{ 285 // You can modify this to turn off JITting without rebuilding the world. 286 return exec->vm().canUseJIT(); 287} 288 289// Returns true if we should try to OSR. 290inline bool jitCompileAndSetHeuristics(CodeBlock* codeBlock, ExecState* exec) 291{ 292 VM& vm = exec->vm(); 293 DeferGCForAWhile deferGC(vm.heap); // My callers don't set top callframe, so we don't want to GC here at all. 294 295 codeBlock->updateAllValueProfilePredictions(); 296 297 if (!codeBlock->checkIfJITThresholdReached()) { 298 if (Options::verboseOSR()) 299 dataLogF(" JIT threshold should be lifted.\n"); 300 return false; 301 } 302 303 switch (codeBlock->jitType()) { 304 case JITCode::BaselineJIT: { 305 if (Options::verboseOSR()) 306 dataLogF(" Code was already compiled.\n"); 307 codeBlock->jitSoon(); 308 return true; 309 } 310 case JITCode::InterpreterThunk: { 311 CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationCanFail); 312 switch (result) { 313 case CompilationFailed: 314 if (Options::verboseOSR()) 315 dataLogF(" JIT compilation failed.\n"); 316 codeBlock->dontJITAnytimeSoon(); 317 return false; 318 case CompilationSuccessful: 319 if (Options::verboseOSR()) 320 dataLogF(" JIT compilation successful.\n"); 321 codeBlock->install(); 322 codeBlock->jitSoon(); 323 return true; 324 default: 325 RELEASE_ASSERT_NOT_REACHED(); 326 return false; 327 } 328 } 329 default: 330 RELEASE_ASSERT_NOT_REACHED(); 331 return false; 332 } 333} 334 335static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* codeBlock, const char *name, EntryKind kind) 336{ 337 if (Options::verboseOSR()) { 338 dataLog( 339 *codeBlock, ": Entered ", name, " with executeCounter = ", 340 codeBlock->llintExecuteCounter(), "\n"); 341 } 342 343 if (!shouldJIT(exec)) { 344 codeBlock->dontJITAnytimeSoon(); 345 LLINT_RETURN_TWO(0, 0); 346 } 347 if (!jitCompileAndSetHeuristics(codeBlock, exec)) 348 LLINT_RETURN_TWO(0, 0); 349 350 if (kind == Prologue) 351 LLINT_RETURN_TWO(codeBlock->jitCode()->executableAddress(), 0); 352 ASSERT(kind == ArityCheck); 353 LLINT_RETURN_TWO(codeBlock->jitCode()->addressForCall( 354 *codeBlock->vm(), codeBlock->ownerExecutable(), MustCheckArity, 355 RegisterPreservationNotRequired).executableAddress(), 0); 356} 357#else // ENABLE(JIT) 358static SlowPathReturnType entryOSR(ExecState* exec, Instruction*, CodeBlock* codeBlock, const char*, EntryKind) 359{ 360 codeBlock->dontJITAnytimeSoon(); 361 LLINT_RETURN_TWO(0, exec); 362} 363#endif // ENABLE(JIT) 364 365LLINT_SLOW_PATH_DECL(entry_osr) 366{ 367 return entryOSR(exec, pc, exec->codeBlock(), "entry_osr", Prologue); 368} 369 370LLINT_SLOW_PATH_DECL(entry_osr_function_for_call) 371{ 372 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call", Prologue); 373} 374 375LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct) 376{ 377 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct", Prologue); 378} 379 380LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck) 381{ 382 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForCall(), "entry_osr_function_for_call_arityCheck", ArityCheck); 383} 384 385LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck) 386{ 387 return entryOSR(exec, pc, jsCast<JSFunction*>(exec->callee())->jsExecutable()->codeBlockForConstruct(), "entry_osr_function_for_construct_arityCheck", ArityCheck); 388} 389 390LLINT_SLOW_PATH_DECL(loop_osr) 391{ 392 CodeBlock* codeBlock = exec->codeBlock(); 393 394#if ENABLE(JIT) 395 if (Options::verboseOSR()) { 396 dataLog( 397 *codeBlock, ": Entered loop_osr with executeCounter = ", 398 codeBlock->llintExecuteCounter(), "\n"); 399 } 400 401 if (!shouldJIT(exec)) { 402 codeBlock->dontJITAnytimeSoon(); 403 LLINT_RETURN_TWO(0, 0); 404 } 405 406 if (!jitCompileAndSetHeuristics(codeBlock, exec)) 407 LLINT_RETURN_TWO(0, 0); 408 409 ASSERT(codeBlock->jitType() == JITCode::BaselineJIT); 410 411 Vector<BytecodeAndMachineOffset> map; 412 codeBlock->jitCodeMap()->decode(map); 413 BytecodeAndMachineOffset* mapping = binarySearch<BytecodeAndMachineOffset, unsigned>(map, map.size(), pc - codeBlock->instructions().begin(), BytecodeAndMachineOffset::getBytecodeIndex); 414 ASSERT(mapping); 415 ASSERT(mapping->m_bytecodeIndex == static_cast<unsigned>(pc - codeBlock->instructions().begin())); 416 417 void* jumpTarget = codeBlock->jitCode()->executableAddressAtOffset(mapping->m_machineCodeOffset); 418 ASSERT(jumpTarget); 419 420 LLINT_RETURN_TWO(jumpTarget, exec->topOfFrame()); 421#else // ENABLE(JIT) 422 UNUSED_PARAM(pc); 423 codeBlock->dontJITAnytimeSoon(); 424 LLINT_RETURN_TWO(0, 0); 425#endif // ENABLE(JIT) 426} 427 428LLINT_SLOW_PATH_DECL(replace) 429{ 430 CodeBlock* codeBlock = exec->codeBlock(); 431 432#if ENABLE(JIT) 433 if (Options::verboseOSR()) { 434 dataLog( 435 *codeBlock, ": Entered replace with executeCounter = ", 436 codeBlock->llintExecuteCounter(), "\n"); 437 } 438 439 if (shouldJIT(exec)) 440 jitCompileAndSetHeuristics(codeBlock, exec); 441 else 442 codeBlock->dontJITAnytimeSoon(); 443 LLINT_END_IMPL(); 444#else // ENABLE(JIT) 445 codeBlock->dontJITAnytimeSoon(); 446 LLINT_END_IMPL(); 447#endif // ENABLE(JIT) 448} 449 450LLINT_SLOW_PATH_DECL(stack_check) 451{ 452 LLINT_BEGIN(); 453#if LLINT_SLOW_PATH_TRACING 454 dataLogF("Checking stack height with exec = %p.\n", exec); 455 dataLogF("CodeBlock = %p.\n", exec->codeBlock()); 456 dataLogF("Num callee registers = %u.\n", exec->codeBlock()->m_numCalleeRegisters); 457 dataLogF("Num vars = %u.\n", exec->codeBlock()->m_numVars); 458 459#if ENABLE(LLINT_C_LOOP) 460 dataLogF("Current end is at %p.\n", exec->vm().jsStackLimit()); 461#else 462 dataLogF("Current end is at %p.\n", exec->vm().stackLimit()); 463#endif 464 465#endif 466 // This stack check is done in the prologue for a function call, and the 467 // CallFrame is not completely set up yet. For example, if the frame needs 468 // an activation object, the activation object will only be set up after 469 // we start executing the function. If we need to throw a StackOverflowError 470 // here, then we need to tell the prologue to start the stack unwinding from 471 // the caller frame (which is fully set up) instead. To do that, we return 472 // the caller's CallFrame in the second return value. 473 // 474 // If the stack check succeeds and we don't need to throw the error, then 475 // we'll return 0 instead. The prologue will check for a non-zero value 476 // when determining whether to set the callFrame or not. 477 478 // For JIT enabled builds which uses the C stack, the stack is not growable. 479 // Hence, if we get here, then we know a stack overflow is imminent. So, just 480 // throw the StackOverflowError unconditionally. 481#if !ENABLE(JIT) 482 ASSERT(!vm.interpreter->stack().containsAddress(exec->topOfFrame())); 483 if (LIKELY(vm.interpreter->stack().ensureCapacityFor(exec->topOfFrame()))) 484 LLINT_RETURN_TWO(pc, 0); 485#endif 486 487 exec = exec->callerFrame(); 488 vm.topCallFrame = exec; 489 ErrorHandlingScope errorScope(vm); 490 CommonSlowPaths::interpreterThrowInCaller(exec, createStackOverflowError(exec)); 491 pc = returnToThrowForThrownException(exec); 492 LLINT_RETURN_TWO(pc, exec); 493} 494 495LLINT_SLOW_PATH_DECL(slow_path_create_activation) 496{ 497 LLINT_BEGIN(); 498#if LLINT_SLOW_PATH_TRACING 499 dataLogF("Creating an activation, exec = %p!\n", exec); 500#endif 501 JSActivation* activation = JSActivation::create(vm, exec, exec->codeBlock()); 502 exec->setScope(activation); 503 LLINT_RETURN(JSValue(activation)); 504} 505 506LLINT_SLOW_PATH_DECL(slow_path_new_object) 507{ 508 LLINT_BEGIN(); 509 LLINT_RETURN(constructEmptyObject(exec, pc[3].u.objectAllocationProfile->structure())); 510} 511 512LLINT_SLOW_PATH_DECL(slow_path_new_array) 513{ 514 LLINT_BEGIN(); 515 LLINT_RETURN(constructArrayNegativeIndexed(exec, pc[4].u.arrayAllocationProfile, bitwise_cast<JSValue*>(&LLINT_OP(2)), pc[3].u.operand)); 516} 517 518LLINT_SLOW_PATH_DECL(slow_path_new_array_with_size) 519{ 520 LLINT_BEGIN(); 521 LLINT_RETURN(constructArrayWithSizeQuirk(exec, pc[3].u.arrayAllocationProfile, exec->lexicalGlobalObject(), LLINT_OP_C(2).jsValue())); 522} 523 524LLINT_SLOW_PATH_DECL(slow_path_new_array_buffer) 525{ 526 LLINT_BEGIN(); 527 LLINT_RETURN(constructArray(exec, pc[4].u.arrayAllocationProfile, exec->codeBlock()->constantBuffer(pc[2].u.operand), pc[3].u.operand)); 528} 529 530LLINT_SLOW_PATH_DECL(slow_path_new_regexp) 531{ 532 LLINT_BEGIN(); 533 RegExp* regExp = exec->codeBlock()->regexp(pc[2].u.operand); 534 if (!regExp->isValid()) 535 LLINT_THROW(createSyntaxError(exec, "Invalid flag supplied to RegExp constructor.")); 536 LLINT_RETURN(RegExpObject::create(vm, exec->lexicalGlobalObject()->regExpStructure(), regExp)); 537} 538 539LLINT_SLOW_PATH_DECL(slow_path_check_has_instance) 540{ 541 LLINT_BEGIN(); 542 543 JSValue value = LLINT_OP_C(2).jsValue(); 544 JSValue baseVal = LLINT_OP_C(3).jsValue(); 545 if (baseVal.isObject()) { 546 JSObject* baseObject = asObject(baseVal); 547 ASSERT(!baseObject->structure()->typeInfo().implementsDefaultHasInstance()); 548 if (baseObject->structure()->typeInfo().implementsHasInstance()) { 549 JSValue result = jsBoolean(baseObject->methodTable()->customHasInstance(baseObject, exec, value)); 550 LLINT_RETURN_WITH_PC_ADJUSTMENT(result, pc[4].u.operand); 551 } 552 } 553 LLINT_THROW(createInvalidParameterError(exec, "instanceof", baseVal)); 554} 555 556LLINT_SLOW_PATH_DECL(slow_path_instanceof) 557{ 558 LLINT_BEGIN(); 559 JSValue value = LLINT_OP_C(2).jsValue(); 560 JSValue proto = LLINT_OP_C(3).jsValue(); 561 ASSERT(!value.isObject() || !proto.isObject()); 562 LLINT_RETURN(jsBoolean(JSObject::defaultHasInstance(exec, value, proto))); 563} 564 565LLINT_SLOW_PATH_DECL(slow_path_get_by_id) 566{ 567 LLINT_BEGIN(); 568 CodeBlock* codeBlock = exec->codeBlock(); 569 const Identifier& ident = codeBlock->identifier(pc[3].u.operand); 570 JSValue baseValue = LLINT_OP_C(2).jsValue(); 571 PropertySlot slot(baseValue); 572 573 JSValue result = baseValue.get(exec, ident, slot); 574 LLINT_CHECK_EXCEPTION(); 575 LLINT_OP(1) = result; 576 577 if (!LLINT_ALWAYS_ACCESS_SLOW 578 && baseValue.isCell() 579 && slot.isCacheable() 580 && slot.slotBase() == baseValue 581 && slot.isCacheableValue()) { 582 583 JSCell* baseCell = baseValue.asCell(); 584 Structure* structure = baseCell->structure(); 585 586 if (!structure->isUncacheableDictionary() 587 && !structure->typeInfo().prohibitsPropertyCaching() 588 && !structure->typeInfo().newImpurePropertyFiresWatchpoints()) { 589 ConcurrentJITLocker locker(codeBlock->m_lock); 590 591 pc[4].u.structure.set( 592 vm, codeBlock->ownerExecutable(), structure); 593 if (isInlineOffset(slot.cachedOffset())) { 594 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id); 595 pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage(); 596 } else { 597 pc[0].u.opcode = LLInt::getOpcode(op_get_by_id_out_of_line); 598 pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue); 599 } 600 } 601 } 602 603 if (!LLINT_ALWAYS_ACCESS_SLOW 604 && isJSArray(baseValue) 605 && ident == exec->propertyNames().length) { 606 pc[0].u.opcode = LLInt::getOpcode(op_get_array_length); 607 ArrayProfile* arrayProfile = codeBlock->getOrAddArrayProfile(pc - codeBlock->instructions().begin()); 608 arrayProfile->observeStructure(baseValue.asCell()->structure()); 609 pc[4].u.arrayProfile = arrayProfile; 610 } 611 612 pc[OPCODE_LENGTH(op_get_by_id) - 1].u.profile->m_buckets[0] = JSValue::encode(result); 613 LLINT_END(); 614} 615 616LLINT_SLOW_PATH_DECL(slow_path_get_arguments_length) 617{ 618 LLINT_BEGIN(); 619 CodeBlock* codeBlock = exec->codeBlock(); 620 const Identifier& ident = codeBlock->identifier(pc[3].u.operand); 621 JSValue baseValue = LLINT_OP(2).jsValue(); 622 PropertySlot slot(baseValue); 623 LLINT_RETURN(baseValue.get(exec, ident, slot)); 624} 625 626LLINT_SLOW_PATH_DECL(slow_path_put_by_id) 627{ 628 LLINT_BEGIN(); 629 CodeBlock* codeBlock = exec->codeBlock(); 630 const Identifier& ident = codeBlock->identifier(pc[2].u.operand); 631 632 JSValue baseValue = LLINT_OP_C(1).jsValue(); 633 PutPropertySlot slot(baseValue, codeBlock->isStrictMode(), codeBlock->putByIdContext()); 634 if (pc[8].u.operand) 635 asObject(baseValue)->putDirect(vm, ident, LLINT_OP_C(3).jsValue(), slot); 636 else 637 baseValue.put(exec, ident, LLINT_OP_C(3).jsValue(), slot); 638 LLINT_CHECK_EXCEPTION(); 639 640 if (!LLINT_ALWAYS_ACCESS_SLOW 641 && baseValue.isCell() 642 && slot.isCacheablePut()) { 643 644 JSCell* baseCell = baseValue.asCell(); 645 Structure* structure = baseCell->structure(); 646 647 if (!structure->isUncacheableDictionary() 648 && !structure->typeInfo().prohibitsPropertyCaching() 649 && baseCell == slot.base()) { 650 651 if (slot.type() == PutPropertySlot::NewProperty) { 652 GCSafeConcurrentJITLocker locker(codeBlock->m_lock, vm.heap); 653 654 if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) { 655 ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated()); 656 657 // This is needed because some of the methods we call 658 // below may GC. 659 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id); 660 661 if (normalizePrototypeChain(exec, baseCell) != InvalidPrototypeChain) { 662 ASSERT(structure->previousID()->isObject()); 663 pc[4].u.structure.set( 664 vm, codeBlock->ownerExecutable(), structure->previousID()); 665 if (isInlineOffset(slot.cachedOffset())) 666 pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage(); 667 else 668 pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue); 669 pc[6].u.structure.set( 670 vm, codeBlock->ownerExecutable(), structure); 671 StructureChain* chain = structure->prototypeChain(exec); 672 ASSERT(chain); 673 pc[7].u.structureChain.set( 674 vm, codeBlock->ownerExecutable(), chain); 675 676 if (pc[8].u.operand) { 677 if (isInlineOffset(slot.cachedOffset())) 678 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct); 679 else 680 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_direct_out_of_line); 681 } else { 682 if (isInlineOffset(slot.cachedOffset())) 683 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal); 684 else 685 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_transition_normal_out_of_line); 686 } 687 } 688 } 689 } else { 690 pc[4].u.structure.set( 691 vm, codeBlock->ownerExecutable(), structure); 692 if (isInlineOffset(slot.cachedOffset())) { 693 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id); 694 pc[5].u.operand = offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + JSObject::offsetOfInlineStorage(); 695 } else { 696 pc[0].u.opcode = LLInt::getOpcode(op_put_by_id_out_of_line); 697 pc[5].u.operand = offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue); 698 } 699 } 700 } 701 } 702 703 LLINT_END(); 704} 705 706LLINT_SLOW_PATH_DECL(slow_path_del_by_id) 707{ 708 LLINT_BEGIN(); 709 CodeBlock* codeBlock = exec->codeBlock(); 710 JSObject* baseObject = LLINT_OP_C(2).jsValue().toObject(exec); 711 bool couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, codeBlock->identifier(pc[3].u.operand)); 712 LLINT_CHECK_EXCEPTION(); 713 if (!couldDelete && codeBlock->isStrictMode()) 714 LLINT_THROW(createTypeError(exec, "Unable to delete property.")); 715 LLINT_RETURN(jsBoolean(couldDelete)); 716} 717 718inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript) 719{ 720 if (LIKELY(baseValue.isCell() && subscript.isString())) { 721 VM& vm = exec->vm(); 722 Structure& structure = *baseValue.asCell()->structure(vm); 723 if (JSCell::canUseFastGetOwnProperty(structure)) { 724 if (JSValue result = baseValue.asCell()->fastGetOwnProperty(vm, structure, asString(subscript)->value(exec))) 725 return result; 726 } 727 } 728 729 if (subscript.isUInt32()) { 730 uint32_t i = subscript.asUInt32(); 731 if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) 732 return asString(baseValue)->getIndex(exec, i); 733 734 return baseValue.get(exec, i); 735 } 736 737 if (isName(subscript)) 738 return baseValue.get(exec, jsCast<NameInstance*>(subscript.asCell())->privateName()); 739 740 Identifier property = subscript.toString(exec)->toIdentifier(exec); 741 return baseValue.get(exec, property); 742} 743 744LLINT_SLOW_PATH_DECL(slow_path_get_by_val) 745{ 746 LLINT_BEGIN(); 747 LLINT_RETURN_PROFILED(op_get_by_val, getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())); 748} 749 750LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val) 751{ 752 LLINT_BEGIN(); 753 JSValue arguments = LLINT_OP(2).jsValue(); 754 if (!arguments) { 755 arguments = Arguments::create(vm, exec); 756 LLINT_CHECK_EXCEPTION(); 757 LLINT_OP(2) = arguments; 758 exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[2].u.operand)).offset()) = arguments; 759 } 760 761 LLINT_RETURN_PROFILED(op_get_argument_by_val, getByVal(exec, arguments, LLINT_OP_C(3).jsValue())); 762} 763 764LLINT_SLOW_PATH_DECL(slow_path_get_by_pname) 765{ 766 LLINT_BEGIN(); 767 LLINT_RETURN(getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())); 768} 769 770LLINT_SLOW_PATH_DECL(slow_path_put_by_val) 771{ 772 LLINT_BEGIN(); 773 774 JSValue baseValue = LLINT_OP_C(1).jsValue(); 775 JSValue subscript = LLINT_OP_C(2).jsValue(); 776 JSValue value = LLINT_OP_C(3).jsValue(); 777 778 if (LIKELY(subscript.isUInt32())) { 779 uint32_t i = subscript.asUInt32(); 780 if (baseValue.isObject()) { 781 JSObject* object = asObject(baseValue); 782 if (object->canSetIndexQuickly(i)) 783 object->setIndexQuickly(vm, i, value); 784 else 785 object->methodTable()->putByIndex(object, exec, i, value, exec->codeBlock()->isStrictMode()); 786 LLINT_END(); 787 } 788 baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode()); 789 LLINT_END(); 790 } 791 792 if (isName(subscript)) { 793 PutPropertySlot slot(baseValue, exec->codeBlock()->isStrictMode()); 794 baseValue.put(exec, jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot); 795 LLINT_END(); 796 } 797 798 Identifier property(exec, subscript.toString(exec)->value(exec)); 799 LLINT_CHECK_EXCEPTION(); 800 PutPropertySlot slot(baseValue, exec->codeBlock()->isStrictMode()); 801 baseValue.put(exec, property, value, slot); 802 LLINT_END(); 803} 804 805LLINT_SLOW_PATH_DECL(slow_path_put_by_val_direct) 806{ 807 LLINT_BEGIN(); 808 809 JSValue baseValue = LLINT_OP_C(1).jsValue(); 810 JSValue subscript = LLINT_OP_C(2).jsValue(); 811 JSValue value = LLINT_OP_C(3).jsValue(); 812 RELEASE_ASSERT(baseValue.isObject()); 813 JSObject* baseObject = asObject(baseValue); 814 if (LIKELY(subscript.isUInt32())) { 815 uint32_t i = subscript.asUInt32(); 816 baseObject->putDirectIndex(exec, i, value); 817 } else if (isName(subscript)) { 818 PutPropertySlot slot(baseObject, exec->codeBlock()->isStrictMode()); 819 baseObject->putDirect(exec->vm(), jsCast<NameInstance*>(subscript.asCell())->privateName(), value, slot); 820 } else { 821 Identifier property(exec, subscript.toString(exec)->value(exec)); 822 if (!exec->vm().exception()) { // Don't put to an object if toString threw an exception. 823 PutPropertySlot slot(baseObject, exec->codeBlock()->isStrictMode()); 824 baseObject->putDirect(exec->vm(), property, value, slot); 825 } 826 } 827 LLINT_END(); 828} 829 830LLINT_SLOW_PATH_DECL(slow_path_del_by_val) 831{ 832 LLINT_BEGIN(); 833 JSValue baseValue = LLINT_OP_C(2).jsValue(); 834 JSObject* baseObject = baseValue.toObject(exec); 835 836 JSValue subscript = LLINT_OP_C(3).jsValue(); 837 838 bool couldDelete; 839 840 uint32_t i; 841 if (subscript.getUInt32(i)) 842 couldDelete = baseObject->methodTable()->deletePropertyByIndex(baseObject, exec, i); 843 else if (isName(subscript)) 844 couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, jsCast<NameInstance*>(subscript.asCell())->privateName()); 845 else { 846 LLINT_CHECK_EXCEPTION(); 847 Identifier property(exec, subscript.toString(exec)->value(exec)); 848 LLINT_CHECK_EXCEPTION(); 849 couldDelete = baseObject->methodTable()->deleteProperty(baseObject, exec, property); 850 } 851 852 if (!couldDelete && exec->codeBlock()->isStrictMode()) 853 LLINT_THROW(createTypeError(exec, "Unable to delete property.")); 854 855 LLINT_RETURN(jsBoolean(couldDelete)); 856} 857 858LLINT_SLOW_PATH_DECL(slow_path_put_by_index) 859{ 860 LLINT_BEGIN(); 861 JSValue arrayValue = LLINT_OP_C(1).jsValue(); 862 ASSERT(isJSArray(arrayValue)); 863 asArray(arrayValue)->putDirectIndex(exec, pc[2].u.operand, LLINT_OP_C(3).jsValue()); 864 LLINT_END(); 865} 866 867LLINT_SLOW_PATH_DECL(slow_path_put_getter_setter) 868{ 869 LLINT_BEGIN(); 870 ASSERT(LLINT_OP(1).jsValue().isObject()); 871 JSObject* baseObj = asObject(LLINT_OP(1).jsValue()); 872 873 GetterSetter* accessor = GetterSetter::create(vm); 874 LLINT_CHECK_EXCEPTION(); 875 876 JSValue getter = LLINT_OP(3).jsValue(); 877 JSValue setter = LLINT_OP(4).jsValue(); 878 ASSERT(getter.isObject() || getter.isUndefined()); 879 ASSERT(setter.isObject() || setter.isUndefined()); 880 ASSERT(getter.isObject() || setter.isObject()); 881 882 if (!getter.isUndefined()) 883 accessor->setGetter(vm, asObject(getter)); 884 if (!setter.isUndefined()) 885 accessor->setSetter(vm, asObject(setter)); 886 baseObj->putDirectAccessor( 887 exec, 888 exec->codeBlock()->identifier(pc[2].u.operand), 889 accessor, Accessor); 890 LLINT_END(); 891} 892 893LLINT_SLOW_PATH_DECL(slow_path_jtrue) 894{ 895 LLINT_BEGIN(); 896 LLINT_BRANCH(op_jtrue, LLINT_OP_C(1).jsValue().toBoolean(exec)); 897} 898 899LLINT_SLOW_PATH_DECL(slow_path_jfalse) 900{ 901 LLINT_BEGIN(); 902 LLINT_BRANCH(op_jfalse, !LLINT_OP_C(1).jsValue().toBoolean(exec)); 903} 904 905LLINT_SLOW_PATH_DECL(slow_path_jless) 906{ 907 LLINT_BEGIN(); 908 LLINT_BRANCH(op_jless, jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue())); 909} 910 911LLINT_SLOW_PATH_DECL(slow_path_jnless) 912{ 913 LLINT_BEGIN(); 914 LLINT_BRANCH(op_jnless, !jsLess<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue())); 915} 916 917LLINT_SLOW_PATH_DECL(slow_path_jgreater) 918{ 919 LLINT_BEGIN(); 920 LLINT_BRANCH(op_jgreater, jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue())); 921} 922 923LLINT_SLOW_PATH_DECL(slow_path_jngreater) 924{ 925 LLINT_BEGIN(); 926 LLINT_BRANCH(op_jngreater, !jsLess<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue())); 927} 928 929LLINT_SLOW_PATH_DECL(slow_path_jlesseq) 930{ 931 LLINT_BEGIN(); 932 LLINT_BRANCH(op_jlesseq, jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue())); 933} 934 935LLINT_SLOW_PATH_DECL(slow_path_jnlesseq) 936{ 937 LLINT_BEGIN(); 938 LLINT_BRANCH(op_jnlesseq, !jsLessEq<true>(exec, LLINT_OP_C(1).jsValue(), LLINT_OP_C(2).jsValue())); 939} 940 941LLINT_SLOW_PATH_DECL(slow_path_jgreatereq) 942{ 943 LLINT_BEGIN(); 944 LLINT_BRANCH(op_jgreatereq, jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue())); 945} 946 947LLINT_SLOW_PATH_DECL(slow_path_jngreatereq) 948{ 949 LLINT_BEGIN(); 950 LLINT_BRANCH(op_jngreatereq, !jsLessEq<false>(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(1).jsValue())); 951} 952 953LLINT_SLOW_PATH_DECL(slow_path_switch_imm) 954{ 955 LLINT_BEGIN(); 956 JSValue scrutinee = LLINT_OP_C(3).jsValue(); 957 ASSERT(scrutinee.isDouble()); 958 double value = scrutinee.asDouble(); 959 int32_t intValue = static_cast<int32_t>(value); 960 int defaultOffset = pc[2].u.operand; 961 if (value == intValue) { 962 CodeBlock* codeBlock = exec->codeBlock(); 963 pc += codeBlock->switchJumpTable(pc[1].u.operand).offsetForValue(intValue, defaultOffset); 964 } else 965 pc += defaultOffset; 966 LLINT_END(); 967} 968 969LLINT_SLOW_PATH_DECL(slow_path_switch_char) 970{ 971 LLINT_BEGIN(); 972 JSValue scrutinee = LLINT_OP_C(3).jsValue(); 973 ASSERT(scrutinee.isString()); 974 JSString* string = asString(scrutinee); 975 ASSERT(string->length() == 1); 976 int defaultOffset = pc[2].u.operand; 977 StringImpl* impl = string->value(exec).impl(); 978 CodeBlock* codeBlock = exec->codeBlock(); 979 pc += codeBlock->switchJumpTable(pc[1].u.operand).offsetForValue((*impl)[0], defaultOffset); 980 LLINT_END(); 981} 982 983LLINT_SLOW_PATH_DECL(slow_path_switch_string) 984{ 985 LLINT_BEGIN(); 986 JSValue scrutinee = LLINT_OP_C(3).jsValue(); 987 int defaultOffset = pc[2].u.operand; 988 if (!scrutinee.isString()) 989 pc += defaultOffset; 990 else { 991 CodeBlock* codeBlock = exec->codeBlock(); 992 pc += codeBlock->stringSwitchJumpTable(pc[1].u.operand).offsetForValue(asString(scrutinee)->value(exec).impl(), defaultOffset); 993 } 994 LLINT_END(); 995} 996 997LLINT_SLOW_PATH_DECL(slow_path_new_func) 998{ 999 LLINT_BEGIN(); 1000 CodeBlock* codeBlock = exec->codeBlock(); 1001 ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsActivation() || exec->hasActivation()); 1002#if LLINT_SLOW_PATH_TRACING 1003 dataLogF("Creating function!\n"); 1004#endif 1005 LLINT_RETURN(JSFunction::create(vm, codeBlock->functionDecl(pc[2].u.operand), exec->scope())); 1006} 1007 1008LLINT_SLOW_PATH_DECL(slow_path_new_func_exp) 1009{ 1010 LLINT_BEGIN(); 1011 CodeBlock* codeBlock = exec->codeBlock(); 1012 FunctionExecutable* function = codeBlock->functionExpr(pc[2].u.operand); 1013 JSFunction* func = JSFunction::create(vm, function, exec->scope()); 1014 1015 LLINT_RETURN(func); 1016} 1017 1018static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, JSValue callee, CodeSpecializationKind kind) 1019{ 1020 UNUSED_PARAM(pc); 1021 1022#if LLINT_SLOW_PATH_TRACING 1023 dataLog("Performing host call.\n"); 1024#endif 1025 1026 ExecState* exec = execCallee->callerFrame(); 1027 VM& vm = exec->vm(); 1028 1029 execCallee->setScope(exec->scope()); 1030 execCallee->setCodeBlock(0); 1031 execCallee->clearReturnPC(); 1032 1033 if (kind == CodeForCall) { 1034 CallData callData; 1035 CallType callType = getCallData(callee, callData); 1036 1037 ASSERT(callType != CallTypeJS); 1038 1039 if (callType == CallTypeHost) { 1040 NativeCallFrameTracer tracer(&vm, execCallee); 1041 execCallee->setCallee(asObject(callee)); 1042 vm.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee)); 1043 1044 LLINT_CALL_RETURN(execCallee, LLInt::getCodePtr(getHostCallReturnValue)); 1045 } 1046 1047#if LLINT_SLOW_PATH_TRACING 1048 dataLog("Call callee is not a function: ", callee, "\n"); 1049#endif 1050 1051 ASSERT(callType == CallTypeNone); 1052 LLINT_CALL_THROW(exec, createNotAFunctionError(exec, callee)); 1053 } 1054 1055 ASSERT(kind == CodeForConstruct); 1056 1057 ConstructData constructData; 1058 ConstructType constructType = getConstructData(callee, constructData); 1059 1060 ASSERT(constructType != ConstructTypeJS); 1061 1062 if (constructType == ConstructTypeHost) { 1063 NativeCallFrameTracer tracer(&vm, execCallee); 1064 execCallee->setCallee(asObject(callee)); 1065 vm.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee)); 1066 1067 LLINT_CALL_RETURN(execCallee, LLInt::getCodePtr(getHostCallReturnValue)); 1068 } 1069 1070#if LLINT_SLOW_PATH_TRACING 1071 dataLog("Constructor callee is not a function: ", callee, "\n"); 1072#endif 1073 1074 ASSERT(constructType == ConstructTypeNone); 1075 LLINT_CALL_THROW(exec, createNotAConstructorError(exec, callee)); 1076} 1077 1078inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, CodeSpecializationKind kind, JSValue calleeAsValue, LLIntCallLinkInfo* callLinkInfo = 0) 1079{ 1080#if LLINT_SLOW_PATH_TRACING 1081 dataLogF("Performing call with recorded PC = %p\n", execCallee->callerFrame()->currentVPC()); 1082#endif 1083 1084 JSCell* calleeAsFunctionCell = getJSFunction(calleeAsValue); 1085 if (!calleeAsFunctionCell) 1086 return handleHostCall(execCallee, pc, calleeAsValue, kind); 1087 1088 JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell); 1089 JSScope* scope = callee->scopeUnchecked(); 1090 VM& vm = *scope->vm(); 1091 execCallee->setScope(scope); 1092 ExecutableBase* executable = callee->executable(); 1093 1094 MacroAssemblerCodePtr codePtr; 1095 CodeBlock* codeBlock = 0; 1096 if (executable->isHostFunction()) 1097 codePtr = executable->entrypointFor(vm, kind, MustCheckArity, RegisterPreservationNotRequired); 1098 else { 1099 FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); 1100 JSObject* error = functionExecutable->prepareForExecution(execCallee, callee, &scope, kind); 1101 execCallee->setScope(scope); 1102 if (error) 1103 LLINT_CALL_THROW(execCallee->callerFrame(), error); 1104 codeBlock = functionExecutable->codeBlockFor(kind); 1105 ASSERT(codeBlock); 1106 ArityCheckMode arity; 1107 if (execCallee->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters())) 1108 arity = MustCheckArity; 1109 else 1110 arity = ArityCheckNotRequired; 1111 codePtr = functionExecutable->entrypointFor(vm, kind, arity, RegisterPreservationNotRequired); 1112 } 1113 1114 ASSERT(!!codePtr); 1115 1116 if (!LLINT_ALWAYS_ACCESS_SLOW && callLinkInfo) { 1117 ExecState* execCaller = execCallee->callerFrame(); 1118 1119 CodeBlock* callerCodeBlock = execCaller->codeBlock(); 1120 1121 ConcurrentJITLocker locker(callerCodeBlock->m_lock); 1122 1123 if (callLinkInfo->isOnList()) 1124 callLinkInfo->remove(); 1125 callLinkInfo->callee.set(vm, callerCodeBlock->ownerExecutable(), callee); 1126 callLinkInfo->lastSeenCallee.set(vm, callerCodeBlock->ownerExecutable(), callee); 1127 callLinkInfo->machineCodeTarget = codePtr; 1128 if (codeBlock) 1129 codeBlock->linkIncomingCall(execCaller, callLinkInfo); 1130 } 1131 1132 LLINT_CALL_RETURN(execCallee, codePtr.executableAddress()); 1133} 1134 1135inline SlowPathReturnType genericCall(ExecState* exec, Instruction* pc, CodeSpecializationKind kind) 1136{ 1137 // This needs to: 1138 // - Set up a call frame. 1139 // - Figure out what to call and compile it if necessary. 1140 // - If possible, link the call's inline cache. 1141 // - Return a tuple of machine code address to call and the new call frame. 1142 1143 JSValue calleeAsValue = LLINT_OP_C(2).jsValue(); 1144 1145 ExecState* execCallee = exec - pc[4].u.operand; 1146 1147 execCallee->setArgumentCountIncludingThis(pc[3].u.operand); 1148 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue; 1149 execCallee->setCallerFrame(exec); 1150 1151 ASSERT(pc[5].u.callLinkInfo); 1152 return setUpCall(execCallee, pc, kind, calleeAsValue, pc[5].u.callLinkInfo); 1153} 1154 1155LLINT_SLOW_PATH_DECL(slow_path_call) 1156{ 1157 LLINT_BEGIN_NO_SET_PC(); 1158 return genericCall(exec, pc, CodeForCall); 1159} 1160 1161LLINT_SLOW_PATH_DECL(slow_path_construct) 1162{ 1163 LLINT_BEGIN_NO_SET_PC(); 1164 return genericCall(exec, pc, CodeForConstruct); 1165} 1166 1167LLINT_SLOW_PATH_DECL(slow_path_size_frame_for_varargs) 1168{ 1169 LLINT_BEGIN(); 1170 // This needs to: 1171 // - Set up a call frame while respecting the variable arguments. 1172 1173 ExecState* execCallee = sizeFrameForVarargs(exec, &vm.interpreter->stack(), 1174 LLINT_OP_C(4).jsValue(), pc[5].u.operand, pc[6].u.operand); 1175 LLINT_CALL_CHECK_EXCEPTION(exec); 1176 1177 vm.newCallFrameReturnValue = execCallee; 1178 1179 LLINT_RETURN_CALLEE_FRAME(execCallee); 1180} 1181 1182LLINT_SLOW_PATH_DECL(slow_path_call_varargs) 1183{ 1184 LLINT_BEGIN_NO_SET_PC(); 1185 // This needs to: 1186 // - Figure out what to call and compile it if necessary. 1187 // - Return a tuple of machine code address to call and the new call frame. 1188 1189 JSValue calleeAsValue = LLINT_OP_C(2).jsValue(); 1190 1191 ExecState* execCallee = vm.newCallFrameReturnValue; 1192 1193 loadVarargs(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand); 1194 LLINT_CALL_CHECK_EXCEPTION(exec); 1195 1196 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue; 1197 execCallee->setCallerFrame(exec); 1198 exec->setCurrentVPC(pc); 1199 1200 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue); 1201} 1202 1203LLINT_SLOW_PATH_DECL(slow_path_construct_varargs) 1204{ 1205 LLINT_BEGIN_NO_SET_PC(); 1206 // This needs to: 1207 // - Figure out what to call and compile it if necessary. 1208 // - Return a tuple of machine code address to call and the new call frame. 1209 1210 JSValue calleeAsValue = LLINT_OP_C(2).jsValue(); 1211 1212 ExecState* execCallee = vm.newCallFrameReturnValue; 1213 1214 loadVarargs(exec, execCallee, LLINT_OP_C(3).jsValue(), LLINT_OP_C(4).jsValue(), pc[6].u.operand); 1215 LLINT_CALL_CHECK_EXCEPTION(exec); 1216 1217 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue; 1218 execCallee->setCallerFrame(exec); 1219 exec->setCurrentVPC(pc); 1220 1221 return setUpCall(execCallee, pc, CodeForConstruct, calleeAsValue); 1222} 1223 1224LLINT_SLOW_PATH_DECL(slow_path_call_eval) 1225{ 1226 LLINT_BEGIN_NO_SET_PC(); 1227 JSValue calleeAsValue = LLINT_OP(2).jsValue(); 1228 1229 ExecState* execCallee = exec - pc[4].u.operand; 1230 1231 execCallee->setArgumentCountIncludingThis(pc[3].u.operand); 1232 execCallee->setCallerFrame(exec); 1233 execCallee->uncheckedR(JSStack::Callee) = calleeAsValue; 1234 execCallee->setScope(exec->scope()); 1235 execCallee->setReturnPC(LLInt::getCodePtr(llint_generic_return_point)); 1236 execCallee->setCodeBlock(0); 1237 exec->setCurrentVPC(pc); 1238 1239 if (!isHostFunction(calleeAsValue, globalFuncEval)) 1240 return setUpCall(execCallee, pc, CodeForCall, calleeAsValue); 1241 1242 vm.hostCallReturnValue = eval(execCallee); 1243 LLINT_CALL_RETURN(execCallee, LLInt::getCodePtr(getHostCallReturnValue)); 1244} 1245 1246LLINT_SLOW_PATH_DECL(slow_path_tear_off_activation) 1247{ 1248 LLINT_BEGIN(); 1249 ASSERT(exec->codeBlock()->needsActivation()); 1250 jsCast<JSActivation*>(LLINT_OP(1).jsValue())->tearOff(vm); 1251 LLINT_END(); 1252} 1253 1254LLINT_SLOW_PATH_DECL(slow_path_tear_off_arguments) 1255{ 1256 LLINT_BEGIN(); 1257 ASSERT(exec->codeBlock()->usesArguments()); 1258 Arguments* arguments = jsCast<Arguments*>(exec->uncheckedR(unmodifiedArgumentsRegister(VirtualRegister(pc[1].u.operand)).offset()).jsValue()); 1259 if (JSValue activationValue = LLINT_OP_C(2).jsValue()) 1260 arguments->didTearOffActivation(exec, jsCast<JSActivation*>(activationValue)); 1261 else 1262 arguments->tearOff(exec); 1263 LLINT_END(); 1264} 1265 1266LLINT_SLOW_PATH_DECL(slow_path_strcat) 1267{ 1268 LLINT_BEGIN(); 1269 LLINT_RETURN(jsStringFromRegisterArray(exec, &LLINT_OP(2), pc[3].u.operand)); 1270} 1271 1272LLINT_SLOW_PATH_DECL(slow_path_to_primitive) 1273{ 1274 LLINT_BEGIN(); 1275 LLINT_RETURN(LLINT_OP_C(2).jsValue().toPrimitive(exec)); 1276} 1277 1278LLINT_SLOW_PATH_DECL(slow_path_get_pnames) 1279{ 1280 LLINT_BEGIN(); 1281 JSValue v = LLINT_OP(2).jsValue(); 1282 if (v.isUndefinedOrNull()) { 1283 pc += pc[5].u.operand; 1284 LLINT_END(); 1285 } 1286 1287 JSObject* o = v.toObject(exec); 1288 Structure* structure = o->structure(); 1289 JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache(); 1290 if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(exec)) 1291 jsPropertyNameIterator = JSPropertyNameIterator::create(exec, o); 1292 1293 LLINT_OP(1) = JSValue(jsPropertyNameIterator); 1294 LLINT_OP(2) = JSValue(o); 1295 LLINT_OP(3) = Register::withInt(0); 1296 LLINT_OP(4) = Register::withInt(jsPropertyNameIterator->size()); 1297 1298 pc += OPCODE_LENGTH(op_get_pnames); 1299 LLINT_END(); 1300} 1301 1302LLINT_SLOW_PATH_DECL(slow_path_next_pname) 1303{ 1304 LLINT_BEGIN(); 1305 JSObject* base = asObject(LLINT_OP(2).jsValue()); 1306 JSString* property = asString(LLINT_OP(1).jsValue()); 1307 if (base->hasProperty(exec, Identifier(exec, property->value(exec)))) { 1308 // Go to target. 1309 pc += pc[6].u.operand; 1310 } // Else, don't change the PC, so the interpreter will reloop. 1311 LLINT_END(); 1312} 1313 1314LLINT_SLOW_PATH_DECL(slow_path_push_with_scope) 1315{ 1316 LLINT_BEGIN(); 1317 JSValue v = LLINT_OP_C(1).jsValue(); 1318 JSObject* o = v.toObject(exec); 1319 LLINT_CHECK_EXCEPTION(); 1320 1321 exec->setScope(JSWithScope::create(exec, o)); 1322 1323 LLINT_END(); 1324} 1325 1326LLINT_SLOW_PATH_DECL(slow_path_pop_scope) 1327{ 1328 LLINT_BEGIN(); 1329 exec->setScope(exec->scope()->next()); 1330 LLINT_END(); 1331} 1332 1333LLINT_SLOW_PATH_DECL(slow_path_push_name_scope) 1334{ 1335 LLINT_BEGIN(); 1336 CodeBlock* codeBlock = exec->codeBlock(); 1337 JSNameScope* scope = JSNameScope::create(exec, codeBlock->identifier(pc[1].u.operand), LLINT_OP(2).jsValue(), pc[3].u.operand); 1338 exec->setScope(scope); 1339 LLINT_END(); 1340} 1341 1342LLINT_SLOW_PATH_DECL(slow_path_throw) 1343{ 1344 LLINT_BEGIN(); 1345 LLINT_THROW(LLINT_OP_C(1).jsValue()); 1346} 1347 1348LLINT_SLOW_PATH_DECL(slow_path_throw_static_error) 1349{ 1350 LLINT_BEGIN(); 1351 if (pc[2].u.operand) 1352 LLINT_THROW(createReferenceError(exec, errorDescriptionForValue(exec, LLINT_OP_C(1).jsValue())->value(exec))); 1353 else 1354 LLINT_THROW(createTypeError(exec, errorDescriptionForValue(exec, LLINT_OP_C(1).jsValue())->value(exec))); 1355} 1356 1357LLINT_SLOW_PATH_DECL(slow_path_handle_watchdog_timer) 1358{ 1359 LLINT_BEGIN_NO_SET_PC(); 1360 ASSERT(vm.watchdog); 1361 if (UNLIKELY(vm.watchdog->didFire(exec))) 1362 LLINT_THROW(createTerminatedExecutionException(&vm)); 1363 LLINT_RETURN_TWO(0, exec); 1364} 1365 1366LLINT_SLOW_PATH_DECL(slow_path_debug) 1367{ 1368 LLINT_BEGIN(); 1369 int debugHookID = pc[1].u.operand; 1370 vm.interpreter->debug(exec, static_cast<DebugHookID>(debugHookID)); 1371 1372 LLINT_END(); 1373} 1374 1375LLINT_SLOW_PATH_DECL(slow_path_profile_will_call) 1376{ 1377 LLINT_BEGIN(); 1378 if (LegacyProfiler* profiler = vm.enabledProfiler()) 1379 profiler->willExecute(exec, LLINT_OP(1).jsValue()); 1380 LLINT_END(); 1381} 1382 1383LLINT_SLOW_PATH_DECL(slow_path_profile_did_call) 1384{ 1385 LLINT_BEGIN(); 1386 if (LegacyProfiler* profiler = vm.enabledProfiler()) 1387 profiler->didExecute(exec, LLINT_OP(1).jsValue()); 1388 LLINT_END(); 1389} 1390 1391LLINT_SLOW_PATH_DECL(slow_path_handle_exception) 1392{ 1393 LLINT_BEGIN_NO_SET_PC(); 1394 ASSERT(vm.exception()); 1395 genericUnwind(&vm, exec, vm.exception()); 1396 LLINT_END_IMPL(); 1397} 1398 1399LLINT_SLOW_PATH_DECL(slow_path_resolve_scope) 1400{ 1401 LLINT_BEGIN(); 1402 const Identifier& ident = exec->codeBlock()->identifier(pc[2].u.operand); 1403 LLINT_RETURN(JSScope::resolve(exec, exec->scope(), ident)); 1404} 1405 1406LLINT_SLOW_PATH_DECL(slow_path_get_from_scope) 1407{ 1408 LLINT_BEGIN(); 1409 const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand); 1410 JSObject* scope = jsCast<JSObject*>(LLINT_OP(2).jsValue()); 1411 ResolveModeAndType modeAndType(pc[4].u.operand); 1412 1413 PropertySlot slot(scope); 1414 if (!scope->getPropertySlot(exec, ident, slot)) { 1415 if (modeAndType.mode() == ThrowIfNotFound) 1416 LLINT_RETURN(exec->vm().throwException(exec, createUndefinedVariableError(exec, ident))); 1417 LLINT_RETURN(jsUndefined()); 1418 } 1419 1420 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time. 1421 if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure()->propertyAccessesAreCacheable()) { 1422 if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) { 1423 CodeBlock* codeBlock = exec->codeBlock(); 1424 ConcurrentJITLocker locker(codeBlock->m_lock); 1425 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure()); 1426 pc[6].u.operand = slot.cachedOffset(); 1427 } 1428 } 1429 1430 LLINT_RETURN(slot.getValue(exec, ident)); 1431} 1432 1433LLINT_SLOW_PATH_DECL(slow_path_put_to_scope) 1434{ 1435 LLINT_BEGIN(); 1436 CodeBlock* codeBlock = exec->codeBlock(); 1437 const Identifier& ident = codeBlock->identifier(pc[2].u.operand); 1438 JSObject* scope = jsCast<JSObject*>(LLINT_OP(1).jsValue()); 1439 JSValue value = LLINT_OP_C(3).jsValue(); 1440 ResolveModeAndType modeAndType = ResolveModeAndType(pc[4].u.operand); 1441 1442 if (modeAndType.mode() == ThrowIfNotFound && !scope->hasProperty(exec, ident)) 1443 LLINT_THROW(createUndefinedVariableError(exec, ident)); 1444 1445 PutPropertySlot slot(scope, codeBlock->isStrictMode()); 1446 scope->methodTable()->put(scope, exec, ident, value, slot); 1447 1448 // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time. 1449 if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) { 1450 if (slot.isCacheablePut() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) { 1451 ConcurrentJITLocker locker(codeBlock->m_lock); 1452 pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure()); 1453 pc[6].u.operand = slot.cachedOffset(); 1454 } 1455 } 1456 1457 LLINT_END(); 1458} 1459 1460extern "C" SlowPathReturnType llint_throw_stack_overflow_error(VM* vm, ProtoCallFrame* protoFrame) 1461{ 1462 ExecState* exec = vm->topCallFrame; 1463 if (!exec) 1464 exec = protoFrame->scope()->globalObject()->globalExec(); 1465 throwStackOverflowError(exec); 1466 return encodeResult(0, 0); 1467} 1468 1469#if !ENABLE(JIT) 1470extern "C" SlowPathReturnType llint_stack_check_at_vm_entry(VM* vm, Register* newTopOfStack) 1471{ 1472 bool success = vm->interpreter->stack().ensureCapacityFor(newTopOfStack); 1473 return encodeResult(reinterpret_cast<void*>(success), 0); 1474} 1475#endif 1476 1477extern "C" void llint_write_barrier_slow(ExecState* exec, JSCell* cell) 1478{ 1479 VM& vm = exec->vm(); 1480 vm.heap.writeBarrier(cell); 1481} 1482 1483extern "C" NO_RETURN_DUE_TO_CRASH void llint_crash() 1484{ 1485 CRASH(); 1486} 1487 1488} } // namespace JSC::LLInt 1489