Changeset 69045 in webkit
- Timestamp:
- Oct 4, 2010 3:43:18 PM (13 years ago)
- Location:
- trunk/JavaScriptCore
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/ChangeLog
r69038 r69045 1 2010-10-04 Oliver Hunt <oliver@apple.com> 2 3 Reviewed by Geoff Garen. 4 5 Lazily create activation objects 6 https://bugs.webkit.org/show_bug.cgi?id=47107 7 8 Make it possible to lazily create the activation object 9 for a function that needs one. This allows us to reduce 10 the overhead of entering a function that may require 11 an activation in some cases, but not always. 12 13 This does make exception handling a little more complex as 14 it's now necessary to verify that a callframes activation 15 has been created, and create it if not, in all of the 16 paths used in exception handling. 17 18 We also need to add logic to check for the existence of 19 the activation in the scoped_var opcodes, as well as 20 op_ret, op_ret_object_or_this and op_tearoff_activation 21 so that we can avoid creating an activation unnecesarily 22 on function exit. 23 24 * bytecode/CodeBlock.cpp: 25 (JSC::CodeBlock::dump): 26 (JSC::CodeBlock::reparseForExceptionInfoIfNecessary): 27 (JSC::CodeBlock::createActivation): 28 * bytecode/CodeBlock.h: 29 (JSC::CodeBlock::setActivationRegister): 30 (JSC::CodeBlock::activationRegister): 31 * bytecode/Opcode.h: 32 * bytecompiler/BytecodeGenerator.cpp: 33 (JSC::BytecodeGenerator::BytecodeGenerator): 34 (JSC::BytecodeGenerator::emitNewFunctionInternal): 35 (JSC::BytecodeGenerator::emitNewFunctionExpression): 36 (JSC::BytecodeGenerator::createActivationIfNecessary): 37 * bytecompiler/BytecodeGenerator.h: 38 * interpreter/Interpreter.cpp: 39 (JSC::Interpreter::resolveSkip): 40 (JSC::Interpreter::resolveGlobalDynamic): 41 (JSC::Interpreter::resolveBase): 42 (JSC::Interpreter::unwindCallFrame): 43 (JSC::Interpreter::throwException): 44 (JSC::Interpreter::privateExecute): 45 * jit/JIT.cpp: 46 (JSC::JIT::privateCompileMainPass): 47 * jit/JIT.h: 48 * jit/JITCall32_64.cpp: 49 (JSC::JIT::emit_op_ret): 50 (JSC::JIT::emit_op_ret_object_or_this): 51 * jit/JITOpcodes.cpp: 52 (JSC::JIT::emit_op_end): 53 (JSC::JIT::emit_op_get_scoped_var): 54 (JSC::JIT::emit_op_put_scoped_var): 55 (JSC::JIT::emit_op_tear_off_activation): 56 (JSC::JIT::emit_op_ret): 57 (JSC::JIT::emit_op_ret_object_or_this): 58 (JSC::JIT::emit_op_create_activation): 59 (JSC::JIT::emit_op_resolve_global_dynamic): 60 * jit/JITOpcodes32_64.cpp: 61 (JSC::JIT::emit_op_get_scoped_var): 62 (JSC::JIT::emit_op_put_scoped_var): 63 (JSC::JIT::emit_op_tear_off_activation): 64 (JSC::JIT::emit_op_create_activation): 65 * jit/JITStubs.cpp: 66 (JSC::DEFINE_STUB_FUNCTION): 67 1 68 2010-10-04 Adam Barth <abarth@webkit.org> 2 69 -
trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r67265 r69045 2408 2408 buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */; 2409 2409 compatibilityVersion = "Xcode 2.4"; 2410 developmentRegion = English; 2410 2411 hasScannedForEncodings = 1; 2411 2412 knownRegions = ( -
trunk/JavaScriptCore/bytecode/CodeBlock.cpp
r68339 r69045 35 35 #include "Interpreter.h" 36 36 #include "JIT.h" 37 #include "JSActivation.h" 37 38 #include "JSFunction.h" 38 39 #include "JSStaticScopeObject.h" … … 486 487 break; 487 488 } 488 case op_ enter_with_activation: {489 int r0 = (++it)->u.operand; 490 printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).data());489 case op_create_activation: { 490 int r0 = (++it)->u.operand; 491 printf("[%4d] create_activation %s\n", location, registerName(exec, r0).data()); 491 492 break; 492 493 } … … 723 724 JSValue scope = JSValue((++it)->u.jsCell); 724 725 ++it; 725 int depth = it[2].u.operand;726 int depth = (++it)->u.operand; 726 727 printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth); 727 it += 3;728 728 break; 729 729 } … … 1543 1543 ScopeChainNode* scopeChain = callFrame->scopeChain(); 1544 1544 if (m_needsFullScopeChain) { 1545 if (codeType() == FunctionCode && !callFrame->r(activationRegister()).jsValue()) { 1546 createActivation(callFrame); 1547 scopeChain = callFrame->scopeChain(); 1548 } 1545 1549 ScopeChain sc(scopeChain); 1546 1550 int scopeDelta = sc.localDepth(); … … 1766 1770 } 1767 1771 1772 void CodeBlock::createActivation(CallFrame* callFrame) 1773 { 1774 ASSERT(codeType() == FunctionCode); 1775 ASSERT(needsFullScopeChain()); 1776 ASSERT(!callFrame->r(activationRegister()).jsValue()); 1777 JSActivation* activation = new (callFrame) JSActivation(callFrame, static_cast<FunctionExecutable*>(ownerExecutable())); 1778 callFrame->r(activationRegister()) = JSValue(activation); 1779 callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); 1780 } 1781 1768 1782 } // namespace JSC -
trunk/JavaScriptCore/bytecode/CodeBlock.h
r68171 r69045 409 409 return m_argumentsRegister; 410 410 } 411 void setActivationRegister(int activationRegister) 412 { 413 m_activationRegister = activationRegister; 414 } 415 int activationRegister() 416 { 417 ASSERT(needsFullScopeChain()); 418 return m_activationRegister; 419 } 411 420 bool usesArguments() const { return m_argumentsRegister != -1; } 412 421 … … 420 429 unsigned jumpTarget(int index) const { return m_jumpTargets[index]; } 421 430 unsigned lastJumpTarget() const { return m_jumpTargets.last(); } 431 432 void createActivation(CallFrame*); 422 433 423 434 #if ENABLE(INTERPRETER) … … 549 560 int m_thisRegister; 550 561 int m_argumentsRegister; 562 int m_activationRegister; 551 563 552 564 bool m_needsFullScopeChain; -
trunk/JavaScriptCore/bytecode/Opcode.h
r68338 r69045 40 40 #define FOR_EACH_OPCODE_ID(macro) \ 41 41 macro(op_enter, 1) \ 42 macro(op_ enter_with_activation, 2) \42 macro(op_create_activation, 2) \ 43 43 macro(op_init_lazy_reg, 2) \ 44 44 macro(op_create_arguments, 2) \ -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r68339 r69045 215 215 , m_nextConstantOffset(0) 216 216 , m_globalConstantIndex(0) 217 , m_hasCreatedActivation(true) 217 218 , m_firstLazyFunction(0) 218 219 , m_lastLazyFunction(0) … … 307 308 , m_nextConstantOffset(0) 308 309 , m_globalConstantIndex(0) 310 , m_hasCreatedActivation(false) 309 311 , m_firstLazyFunction(0) 310 312 , m_lastLazyFunction(0) … … 320 322 321 323 codeBlock->setGlobalData(m_globalData); 322 324 325 emitOpcode(op_enter); 323 326 if (m_codeBlock->needsFullScopeChain()) { 324 327 m_activationRegister = addVar(); 325 emitOpcode(op_enter_with_activation); 326 instructions().append(m_activationRegister->index()); 327 } else 328 emitOpcode(op_enter); 328 emitInitLazyRegister(m_activationRegister); 329 m_codeBlock->setActivationRegister(m_activationRegister->index()); 330 } 329 331 330 332 // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments' … … 357 359 // Captured variables and functions go first so that activations don't have 358 360 // to step over the non-captured locals to mark them. 361 m_hasCreatedActivation = false; 359 362 if (functionBody->hasCapturedVariables()) { 360 363 for (size_t i = 0; i < functionStack.size(); ++i) { … … 362 365 const Identifier& ident = function->ident(); 363 366 if (functionBody->captures(ident)) { 367 if (!m_hasCreatedActivation) { 368 m_hasCreatedActivation = true; 369 emitOpcode(op_create_activation); 370 instructions().append(m_activationRegister->index()); 371 } 364 372 m_functions.add(ident.impl()); 365 373 emitNewFunction(addVar(ident, false), function); … … 372 380 } 373 381 } 374 bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables(); 382 bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !debugger; 383 if (!canLazilyCreateFunctions && !m_hasCreatedActivation) { 384 m_hasCreatedActivation = true; 385 emitOpcode(op_create_activation); 386 instructions().append(m_activationRegister->index()); 387 } 388 375 389 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 376 390 m_firstLazyFunction = codeBlock->m_numVars; … … 400 414 if (debugger) 401 415 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 402 403 416 404 417 FunctionParameters& parameters = *functionBody->parameters(); … … 449 462 , m_nextConstantOffset(0) 450 463 , m_globalConstantIndex(0) 464 , m_hasCreatedActivation(true) 451 465 , m_firstLazyFunction(0) 452 466 , m_lastLazyFunction(0) … … 1505 1519 RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck) 1506 1520 { 1521 createActivationIfNecessary(); 1507 1522 emitOpcode(op_new_func); 1508 1523 instructions().append(dst->index()); … … 1524 1539 FunctionBodyNode* function = n->body(); 1525 1540 unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function)); 1526 1541 1542 createActivationIfNecessary(); 1527 1543 emitOpcode(op_new_func_exp); 1528 1544 instructions().append(r0->index()); … … 1544 1560 emitOpcode(op_create_arguments); 1545 1561 instructions().append(m_codeBlock->argumentsRegister()); 1562 } 1563 1564 void BytecodeGenerator::createActivationIfNecessary() 1565 { 1566 if (m_hasCreatedActivation) 1567 return; 1568 if (!m_codeBlock->needsFullScopeChain()) 1569 return; 1570 emitOpcode(op_create_activation); 1571 instructions().append(m_activationRegister->index()); 1546 1572 } 1547 1573 -
trunk/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r68899 r69045 519 519 520 520 void createArgumentsIfNecessary(); 521 void createActivationIfNecessary(); 521 522 RegisterID* createLazyRegisterIfNecessary(RegisterID*); 522 523 … … 559 560 int m_globalVarStorageOffset; 560 561 562 bool m_hasCreatedActivation; 561 563 int m_firstLazyFunction; 562 564 int m_lastLazyFunction; -
trunk/JavaScriptCore/interpreter/Interpreter.cpp
r68455 r69045 128 128 ScopeChainIterator end = scopeChain->end(); 129 129 ASSERT(iter != end); 130 bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); 131 ASSERT(skip || !checkTopLevel); 132 if (checkTopLevel && skip--) { 133 if (callFrame->r(codeBlock->activationRegister()).jsValue()) 134 ++iter; 135 } 130 136 while (skip--) { 131 137 ++iter; … … 141 147 if (exceptionValue) 142 148 return false; 149 ASSERT(result); 143 150 callFrame->r(dst) = JSValue(result); 144 151 return true; … … 204 211 ScopeChainIterator end = scopeChain->end(); 205 212 ASSERT(iter != end); 213 bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); 214 ASSERT(skip || !checkTopLevel); 215 if (checkTopLevel && skip--) { 216 if (callFrame->r(codeBlock->activationRegister()).jsValue()) 217 ++iter; 218 } 206 219 while (skip--) { 207 220 JSObject* o = *iter; … … 215 228 if (exceptionValue) 216 229 return false; 230 ASSERT(result); 217 231 callFrame->r(dst) = JSValue(result); 218 232 return true; … … 231 245 if (structure == globalObject->structure()) { 232 246 callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset)); 247 ASSERT(callFrame->r(dst).jsValue()); 233 248 return true; 234 249 } … … 244 259 vPC[3] = globalObject->structure(); 245 260 vPC[4] = slot.cachedOffset(); 261 ASSERT(result); 246 262 callFrame->r(dst) = JSValue(result); 247 263 return true; … … 251 267 if (exceptionValue) 252 268 return false; 269 ASSERT(result); 253 270 callFrame->r(dst) = JSValue(result); 254 271 return true; … … 264 281 int property = vPC[2].u.operand; 265 282 callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain())); 283 ASSERT(callFrame->r(dst).jsValue()); 266 284 } 267 285 … … 536 554 // If this call frame created an activation or an 'arguments' object, tear it off. 537 555 if (oldCodeBlock->codeType() == FunctionCode && oldCodeBlock->needsFullScopeChain()) { 556 if (!callFrame->r(oldCodeBlock->activationRegister()).jsValue()) { 557 oldCodeBlock->createActivation(callFrame); 558 scopeChain = callFrame->scopeChain(); 559 } 538 560 while (!scopeChain->object->inherits(&JSActivation::info)) 539 561 scopeChain = scopeChain->pop(); … … 647 669 ScopeChainNode* scopeChain = callFrame->scopeChain(); 648 670 ScopeChain sc(scopeChain); 649 int scopeDelta = depth(codeBlock, sc) - handler->scopeDepth; 671 int scopeDelta = 0; 672 if (!codeBlock->needsFullScopeChain() || codeBlock->codeType() != FunctionCode 673 || callFrame->r(codeBlock->activationRegister()).jsValue()) 674 scopeDelta = depth(codeBlock, sc) - handler->scopeDepth; 650 675 ASSERT(scopeDelta >= 0); 651 676 while (scopeDelta--) … … 1519 1544 int dst = vPC[1].u.operand; 1520 1545 int src = vPC[2].u.operand; 1546 1521 1547 callFrame->r(dst) = callFrame->r(src); 1522 1548 … … 2328 2354 ScopeChainIterator end = scopeChain->end(); 2329 2355 ASSERT(iter != end); 2356 ASSERT(codeBlock == callFrame->codeBlock()); 2357 bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); 2358 ASSERT(skip || !checkTopLevel); 2359 if (checkTopLevel && skip--) { 2360 if (callFrame->r(codeBlock->activationRegister()).jsValue()) 2361 ++iter; 2362 } 2330 2363 while (skip--) { 2331 2364 ++iter; … … 2335 2368 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); 2336 2369 callFrame->r(dst) = scope->registerAt(index); 2370 ASSERT(callFrame->r(dst).jsValue()); 2337 2371 vPC += OPCODE_LENGTH(op_get_scoped_var); 2338 2372 NEXT_INSTRUCTION(); … … 2349 2383 ScopeChainIterator iter = scopeChain->begin(); 2350 2384 ScopeChainIterator end = scopeChain->end(); 2385 ASSERT(codeBlock == callFrame->codeBlock()); 2351 2386 ASSERT(iter != end); 2387 bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); 2388 ASSERT(skip || !checkTopLevel); 2389 if (checkTopLevel && skip--) { 2390 if (callFrame->r(codeBlock->activationRegister()).jsValue()) 2391 ++iter; 2392 } 2352 2393 while (skip--) { 2353 2394 ++iter; … … 2357 2398 ASSERT((*iter)->isVariableObject()); 2358 2399 JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); 2400 ASSERT(callFrame->r(value).jsValue()); 2359 2401 scope->registerAt(index) = JSValue(callFrame->r(value).jsValue()); 2360 2402 vPC += OPCODE_LENGTH(op_put_scoped_var); … … 3659 3701 int func = vPC[2].u.operand; 3660 3702 int shouldCheck = vPC[3].u.operand; 3661 3703 ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); 3662 3704 if (!shouldCheck || !callFrame->r(dst).jsValue()) 3663 3705 callFrame->r(dst) = JSValue(codeBlock->functionDecl(func)->make(callFrame, callFrame->scopeChain())); … … 3676 3718 int dst = vPC[1].u.operand; 3677 3719 int funcIndex = vPC[2].u.operand; 3678 3720 3721 ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); 3679 3722 FunctionExecutable* function = codeBlock->functionExpr(funcIndex); 3680 3723 JSFunction* func = function->make(callFrame, callFrame->scopeChain()); … … 3712 3755 int argCount = vPC[2].u.operand; 3713 3756 int registerOffset = vPC[3].u.operand; 3714 3757 3758 ASSERT(codeBlock->codeType() != FunctionCode || !codeBlock->needsFullScopeChain() || callFrame->r(codeBlock->activationRegister()).jsValue()); 3715 3759 JSValue funcVal = callFrame->r(func).jsValue(); 3716 3760 … … 3981 4025 */ 3982 4026 3983 int src1= vPC[1].u.operand;3984 int src2= vPC[2].u.operand;4027 int activation = vPC[1].u.operand; 4028 int arguments = vPC[2].u.operand; 3985 4029 ASSERT(codeBlock->needsFullScopeChain()); 3986 3987 JSActivation* activation = asActivation(callFrame->r(src1).jsValue()); 3988 activation->copyRegisters(); 3989 3990 if (JSValue arguments = callFrame->r(unmodifiedArgumentsRegister(src2)).jsValue()) 3991 asArguments(arguments)->setActivation(activation); 4030 JSValue activationValue = callFrame->r(activation).jsValue(); 4031 if (activationValue) { 4032 asActivation(activationValue)->copyRegisters(); 4033 4034 if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) 4035 asArguments(argumentsValue)->setActivation(asActivation(activationValue)); 4036 } else if (JSValue argumentsValue = callFrame->r(unmodifiedArgumentsRegister(arguments)).jsValue()) 4037 asArguments(argumentsValue)->copyRegisters(); 3992 4038 3993 4039 vPC += OPCODE_LENGTH(op_tear_off_activation); … … 4027 4073 int result = vPC[1].u.operand; 4028 4074 4029 if (callFrame->codeBlock()->needsFullScopeChain() )4075 if (callFrame->codeBlock()->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue()) 4030 4076 callFrame->scopeChain()->deref(); 4031 4077 … … 4068 4114 int result = vPC[1].u.operand; 4069 4115 4070 if (codeBlock->needsFullScopeChain() )4116 if (codeBlock->needsFullScopeChain() && callFrame->r(codeBlock->activationRegister()).jsValue()) 4071 4117 callFrame->scopeChain()->deref(); 4072 4118 … … 4104 4150 NEXT_INSTRUCTION(); 4105 4151 } 4106 DEFINE_OPCODE(op_enter_with_activation) { 4107 /* enter_with_activation dst(r) 4108 4109 Initializes local variables to undefined, creates an activation object, 4110 places it in dst, and pushes it onto the scope chain. 4111 4112 This opcode appears only at the beginning of a code block. 4113 */ 4114 4115 size_t i = 0; 4116 for (size_t count = codeBlock->m_numVars; i < count; ++i) 4117 callFrame->r(i) = jsUndefined(); 4118 4119 int dst = vPC[1].u.operand; 4120 JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable())); 4121 callFrame->r(dst) = JSValue(activation); 4122 callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); 4123 4124 vPC += OPCODE_LENGTH(op_enter_with_activation); 4152 DEFINE_OPCODE(op_create_activation) { 4153 /* create_activation dst(r) 4154 4155 If the activation object for this callframe has not yet been created, 4156 this creates it and writes it back to dst. 4157 */ 4158 4159 int activationReg = vPC[1].u.operand; 4160 if (!callFrame->r(activationReg).jsValue()) { 4161 JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable())); 4162 callFrame->r(activationReg) = JSValue(activation); 4163 callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); 4164 } 4165 vPC += OPCODE_LENGTH(op_create_activation); 4125 4166 NEXT_INSTRUCTION(); 4126 4167 } -
trunk/JavaScriptCore/jit/JIT.cpp
r68338 r69045 235 235 DEFINE_OP(op_end) 236 236 DEFINE_OP(op_enter) 237 DEFINE_OP(op_ enter_with_activation)237 DEFINE_OP(op_create_activation) 238 238 DEFINE_OP(op_eq) 239 239 DEFINE_OP(op_eq_null) -
trunk/JavaScriptCore/jit/JIT.h
r68338 r69045 745 745 void emit_op_end(Instruction*); 746 746 void emit_op_enter(Instruction*); 747 void emit_op_ enter_with_activation(Instruction*);747 void emit_op_create_activation(Instruction*); 748 748 void emit_op_eq(Instruction*); 749 749 void emit_op_eq_null(Instruction*); -
trunk/JavaScriptCore/jit/JITCall32_64.cpp
r67990 r69045 109 109 110 110 // We could JIT generate the deref, only calling out to C when the refcount hits zero. 111 if (m_codeBlock->needsFullScopeChain()) 111 if (m_codeBlock->needsFullScopeChain()) { 112 Jump activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); 112 113 JITStubCall(this, cti_op_ret_scopeChain).call(); 113 114 activationNotCreated.link(this); 115 } 114 116 emitLoad(dst, regT1, regT0); 115 117 emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT2); … … 126 128 127 129 // We could JIT generate the deref, only calling out to C when the refcount hits zero. 128 if (m_codeBlock->needsFullScopeChain()) 130 if (m_codeBlock->needsFullScopeChain()) { 131 Jump activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); 129 132 JITStubCall(this, cti_op_ret_scopeChain).call(); 133 activationNotCreated.link(this); 134 } 130 135 131 136 emitLoad(result, regT1, regT0); -
trunk/JavaScriptCore/jit/JITOpcodes.cpp
r68339 r69045 338 338 if (m_codeBlock->needsFullScopeChain()) 339 339 JITStubCall(this, cti_op_end).call(); 340 340 341 ASSERT(returnValueRegister != callFrameRegister); 341 342 emitGetVirtualRegister(currentInstruction[1].u.operand, returnValueRegister); … … 468 469 469 470 emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0); 471 bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); 472 ASSERT(skip || !checkTopLevel); 473 if (checkTopLevel && skip--) { 474 Jump activationNotCreated; 475 if (checkTopLevel) 476 activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); 477 loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0); 478 activationNotCreated.link(this); 479 } 470 480 while (skip--) 471 481 loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0); … … 482 492 emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1); 483 493 emitGetVirtualRegister(currentInstruction[3].u.operand, regT0); 494 bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); 495 ASSERT(skip || !checkTopLevel); 496 if (checkTopLevel && skip--) { 497 Jump activationNotCreated; 498 if (checkTopLevel) 499 activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); 500 loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1); 501 activationNotCreated.link(this); 502 } 484 503 while (skip--) 485 504 loadPtr(Address(regT1, OBJECT_OFFSETOF(ScopeChainNode, next)), regT1); … … 491 510 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction) 492 511 { 512 unsigned activation = currentInstruction[1].u.operand; 513 unsigned arguments = currentInstruction[2].u.operand; 514 Jump activationCreated = branchTestPtr(NonZero, addressFor(activation)); 515 Jump argumentsNotCreated = branchTestPtr(Zero, addressFor(arguments)); 516 activationCreated.link(this); 493 517 JITStubCall stubCall(this, cti_op_tear_off_activation); 494 stubCall.addArgument( currentInstruction[1].u.operand, regT2);495 stubCall.addArgument(unmodifiedArgumentsRegister( currentInstruction[2].u.operand), regT2);518 stubCall.addArgument(activation, regT2); 519 stubCall.addArgument(unmodifiedArgumentsRegister(arguments), regT2); 496 520 stubCall.call(); 521 argumentsNotCreated.link(this); 497 522 } 498 523 … … 511 536 { 512 537 // We could JIT generate the deref, only calling out to C when the refcount hits zero. 513 if (m_codeBlock->needsFullScopeChain()) 538 if (m_codeBlock->needsFullScopeChain()) { 539 Jump activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); 514 540 JITStubCall(this, cti_op_ret_scopeChain).call(); 515 541 activationNotCreated.link(this); 542 } 516 543 ASSERT(callFrameRegister != regT1); 517 544 ASSERT(regT1 != returnValueRegister); … … 535 562 { 536 563 // We could JIT generate the deref, only calling out to C when the refcount hits zero. 537 if (m_codeBlock->needsFullScopeChain()) 564 if (m_codeBlock->needsFullScopeChain()) { 565 Jump activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); 538 566 JITStubCall(this, cti_op_ret_scopeChain).call(); 567 activationNotCreated.link(this); 568 } 539 569 540 570 ASSERT(callFrameRegister != regT1); … … 1186 1216 } 1187 1217 1188 void JIT::emit_op_enter_with_activation(Instruction* currentInstruction) 1189 { 1190 // Even though CTI doesn't use them, we initialize our constant 1191 // registers to zap stale pointers, to avoid unnecessarily prolonging 1192 // object lifetime and increasing GC pressure. 1193 size_t count = m_codeBlock->m_numVars; 1194 for (size_t j = 0; j < count; ++j) 1195 emitInitRegister(j); 1196 1218 void JIT::emit_op_create_activation(Instruction* currentInstruction) 1219 { 1220 unsigned dst = currentInstruction[1].u.operand; 1221 1222 Jump activationCreated = branchTestPtr(NonZero, Address(callFrameRegister, sizeof(Register) * dst)); 1197 1223 JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand); 1224 emitPutVirtualRegister(dst); 1225 activationCreated.link(this); 1198 1226 } 1199 1227 … … 1560 1588 1561 1589 emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT0); 1590 1591 bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); 1592 ASSERT(skip || !checkTopLevel); 1593 if (checkTopLevel && skip--) { 1594 Jump activationNotCreated; 1595 if (checkTopLevel) 1596 activationNotCreated = branchTestPtr(Zero, addressFor(m_codeBlock->activationRegister())); 1597 loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1); 1598 addSlowCase(checkStructure(regT1, m_globalData->activationStructure.get())); 1599 loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, next)), regT0); 1600 activationNotCreated.link(this); 1601 } 1562 1602 while (skip--) { 1563 1603 loadPtr(Address(regT0, OBJECT_OFFSETOF(ScopeChainNode, object)), regT1); -
trunk/JavaScriptCore/jit/JITOpcodes32_64.cpp
r68338 r69045 611 611 612 612 emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2); 613 bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); 614 ASSERT(skip || !checkTopLevel); 615 if (checkTopLevel && skip--) { 616 Jump activationNotCreated; 617 if (checkTopLevel) 618 activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); 619 loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); 620 activationNotCreated.link(this); 621 } 613 622 while (skip--) 614 623 loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); … … 632 641 633 642 emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT2); 643 bool checkTopLevel = m_codeBlock->codeType() == FunctionCode && m_codeBlock->needsFullScopeChain(); 644 ASSERT(skip || !checkTopLevel); 645 if (checkTopLevel && skip--) { 646 Jump activationNotCreated; 647 if (checkTopLevel) 648 activationNotCreated = branch32(Equal, tagFor(m_codeBlock->activationRegister()), Imm32(JSValue::EmptyValueTag)); 649 loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); 650 activationNotCreated.link(this); 651 } 634 652 while (skip--) 635 653 loadPtr(Address(regT2, OBJECT_OFFSETOF(ScopeChainNode, next)), regT2); … … 645 663 void JIT::emit_op_tear_off_activation(Instruction* currentInstruction) 646 664 { 665 unsigned activation = currentInstruction[1].u.operand; 666 unsigned arguments = currentInstruction[2].u.operand; 667 Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag)); 668 Jump argumentsNotCreated = branch32(Equal, tagFor(arguments), Imm32(JSValue::EmptyValueTag)); 669 activationCreated.link(this); 647 670 JITStubCall stubCall(this, cti_op_tear_off_activation); 648 671 stubCall.addArgument(currentInstruction[1].u.operand); 649 672 stubCall.addArgument(unmodifiedArgumentsRegister(currentInstruction[2].u.operand)); 650 673 stubCall.call(); 674 argumentsNotCreated.link(this); 651 675 } 652 676 … … 1468 1492 } 1469 1493 1470 void JIT::emit_op_enter_with_activation(Instruction* currentInstruction) 1471 { 1472 emit_op_enter(currentInstruction); 1473 1474 JITStubCall(this, cti_op_push_activation).call(currentInstruction[1].u.operand); 1494 void JIT::emit_op_create_activation(Instruction* currentInstruction) 1495 { 1496 unsigned activation = currentInstruction[1].u.operand; 1497 1498 Jump activationCreated = branch32(NotEqual, tagFor(activation), Imm32(JSValue::EmptyValueTag)); 1499 JITStubCall(this, cti_op_push_activation).call(activation); 1500 activationCreated.link(this); 1475 1501 } 1476 1502 -
trunk/JavaScriptCore/jit/JITStubs.cpp
r67943 r69045 1907 1907 { 1908 1908 STUB_INIT_STACK_FRAME(stackFrame); 1909 1909 1910 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue()); 1910 1911 return stackFrame.args[0].function()->make(stackFrame.callFrame, stackFrame.callFrame->scopeChain()); 1911 1912 } … … 2214 2215 2215 2216 ASSERT(stackFrame.callFrame->codeBlock()->needsFullScopeChain()); 2217 JSValue activationValue = stackFrame.args[0].jsValue(); 2218 if (!activationValue) { 2219 if (JSValue v = stackFrame.args[1].jsValue()) 2220 asArguments(v)->copyRegisters(); 2221 return; 2222 } 2216 2223 JSActivation* activation = asActivation(stackFrame.args[0].jsValue()); 2217 2224 activation->copyRegisters(); … … 2686 2693 ScopeChainIterator end = scopeChain->end(); 2687 2694 ASSERT(iter != end); 2695 CodeBlock* codeBlock = callFrame->codeBlock(); 2696 bool checkTopLevel = codeBlock->codeType() == FunctionCode && codeBlock->needsFullScopeChain(); 2697 ASSERT(skip || !checkTopLevel); 2698 if (checkTopLevel && skip--) { 2699 if (callFrame->r(codeBlock->activationRegister()).jsValue()) 2700 ++iter; 2701 } 2688 2702 while (skip--) { 2689 2703 ++iter; … … 2701 2715 } while (++iter != end); 2702 2716 2703 CodeBlock* codeBlock = callFrame->codeBlock();2704 2717 unsigned vPCIndex = codeBlock->bytecodeOffset(callFrame, STUB_RETURN_ADDRESS); 2705 2718 stackFrame.globalData->exception = createUndefinedVariableError(callFrame, ident, vPCIndex, codeBlock); … … 3050 3063 FunctionExecutable* function = stackFrame.args[0].function(); 3051 3064 JSFunction* func = function->make(callFrame, callFrame->scopeChain()); 3065 ASSERT(callFrame->codeBlock()->codeType() != FunctionCode || !callFrame->codeBlock()->needsFullScopeChain() || callFrame->r(callFrame->codeBlock()->activationRegister()).jsValue()); 3052 3066 3053 3067 /* … … 3156 3170 { 3157 3171 STUB_INIT_STACK_FRAME(stackFrame); 3172 ASSERT(stackFrame.callFrame->codeBlock()->codeType() != FunctionCode || !stackFrame.callFrame->codeBlock()->needsFullScopeChain() || stackFrame.callFrame->r(stackFrame.callFrame->codeBlock()->activationRegister()).jsValue()); 3158 3173 3159 3174 CallFrame* callFrame = stackFrame.callFrame;
Note: See TracChangeset
for help on using the changeset viewer.