Changeset 127939 in webkit for trunk/Source/JavaScriptCore/bytecompiler
- Timestamp:
- Sep 7, 2012, 4:59:10 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore/bytecompiler
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r127810 r127939 279 279 , m_nextConstantOffset(0) 280 280 , m_globalConstantIndex(0) 281 , m_hasCreatedActivation(true)282 , m_firstLazyFunction(0)283 , m_lastLazyFunction(0)284 281 , m_globalData(scope->globalData()) 285 282 , m_lastOpcodeID(op_end) … … 321 318 322 319 for (size_t i = 0; i < functionStack.size(); ++i) { 323 FunctionBodyNode* function = functionStack[i] ;320 FunctionBodyNode* function = functionStack[i].node; 324 321 bool propertyDidExist = 325 322 globalObject->removeDirect(*m_globalData, function->ident()); // Newly declared functions overwrite existing properties. … … 333 330 334 331 for (size_t i = 0; i < varStack.size(); ++i) { 335 if (globalObject->hasProperty(exec, *varStack[i]. first))332 if (globalObject->hasProperty(exec, *varStack[i].name)) 336 333 continue; 337 334 addGlobalVar( 338 *varStack[i]. first,339 (varStack[i]. second& DeclarationStacks::IsConstant) ? IsConstant : IsVariable,335 *varStack[i].name, 336 (varStack[i].attributes & DeclarationStacks::IsConstant) ? IsConstant : IsVariable, 340 337 NotFunctionOrNotSpecializable); 338 } 339 } 340 341 void BytecodeGenerator::allocateCapturedVars() 342 { 343 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 344 if (!node->hasCapturedVariables()) 345 return; 346 347 DeclarationStacks::FunctionStack& functionStack = node->functionStack(); 348 for (size_t i = 0; i < functionStack.size(); ++i) { 349 if (!node->captures(functionStack[i].node->ident())) 350 continue; 351 functionStack[i].reg = addVar(functionStack[i].node->ident(), false); 352 m_functions.add(functionStack[i].node->ident().impl()); 353 } 354 355 DeclarationStacks::VarStack& varStack = node->varStack(); 356 for (size_t i = 0; i < varStack.size(); ++i) { 357 if (!node->captures(*varStack[i].name)) 358 continue; 359 varStack[i].reg = addVar(*varStack[i].name, varStack[i].attributes & DeclarationStacks::IsConstant); 360 } 361 } 362 363 void BytecodeGenerator::allocateUncapturedVars() 364 { 365 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 366 367 DeclarationStacks::FunctionStack& functionStack = node->functionStack(); 368 for (size_t i = 0; i < functionStack.size(); ++i) { 369 if (node->captures(functionStack[i].node->ident())) 370 continue; 371 functionStack[i].reg = addVar(functionStack[i].node->ident(), false); 372 m_functions.add(functionStack[i].node->ident().impl()); 373 } 374 375 DeclarationStacks::VarStack& varStack = node->varStack(); 376 for (size_t i = 0; i < varStack.size(); ++i) { 377 if (node->captures(*varStack[i].name)) 378 continue; 379 varStack[i].reg = addVar(*varStack[i].name, varStack[i].attributes & DeclarationStacks::IsConstant); 380 } 381 } 382 383 void BytecodeGenerator::allocateActivationVar() 384 { 385 if (!m_codeBlock->needsFullScopeChain()) 386 return; 387 388 m_activationRegister = addVar(); 389 m_codeBlock->setActivationRegister(m_activationRegister->index()); 390 } 391 392 void BytecodeGenerator::allocateArgumentsVars() 393 { 394 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 395 396 // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments' 397 // object, if created. 398 if (!m_codeBlock->needsFullScopeChain() && !node->usesArguments()) 399 return; 400 401 RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code. 402 RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'. 403 404 // We can save a little space by hard-coding the knowledge that the two 405 // 'arguments' values are stored in consecutive registers, and storing 406 // only the index of the assignable one. 407 m_codeBlock->setArgumentsRegister(argumentsRegister->index()); 408 ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(m_codeBlock->argumentsRegister())); 409 } 410 411 void BytecodeGenerator::allocateCalleeVarUndeclared() 412 { 413 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 414 415 if (node->ident().isNull() || !node->functionNameIsInScope()) 416 return; 417 418 // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. 419 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) 420 return; 421 422 if (!node->captures(node->ident())) { 423 m_calleeRegister.setIndex(RegisterFile::Callee); 424 return; 425 } 426 427 m_calleeRegister.setIndex(addVar()->index()); 428 } 429 430 void BytecodeGenerator::declareParameters() 431 { 432 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 433 FunctionParameters& parameters = *node->parameters(); 434 m_parameters.grow(parameters.size() + 1); // reserve space for "this" 435 436 // Add "this" as a parameter 437 int nextParameterIndex = CallFrame::thisArgumentOffset(); 438 m_thisRegister.setIndex(nextParameterIndex--); 439 m_codeBlock->addParameter(); 440 441 for (size_t i = 0; i < parameters.size(); ++i) 442 declareParameter(parameters[i], nextParameterIndex--); 443 } 444 445 void BytecodeGenerator::declareCallee() 446 { 447 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 448 449 if (node->ident().isNull() || !node->functionNameIsInScope()) 450 return; 451 452 // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. 453 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) 454 return; 455 456 symbolTable().add(node->ident().impl(), SymbolTableEntry(m_calleeRegister.index(), ReadOnly)); 457 } 458 459 void BytecodeGenerator::initCalleeVar() 460 { 461 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 462 463 if (node->ident().isNull() || !node->functionNameIsInScope()) 464 return; 465 466 // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. 467 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) { 468 emitOpcode(op_push_name_scope); 469 instructions().append(addConstant(node->ident())); 470 instructions().append(RegisterFile::Callee); 471 instructions().append(ReadOnly | DontDelete); 472 473 // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime. 474 m_scope.set(*globalData(), 475 JSNameScope::create( 476 m_scope->globalObject()->globalExec(), 477 node->ident(), 478 jsUndefined(), 479 ReadOnly | DontDelete, 480 m_scope.get() 481 ) 482 ); 483 484 return; 485 } 486 487 if (!node->captures(node->ident())) 488 return; 489 490 // Move the callee into the captured section of the stack. 491 RegisterID callee(RegisterFile::Callee); 492 emitMove(&m_calleeRegister, &callee); 493 } 494 495 void BytecodeGenerator::initArgumentsVars() 496 { 497 if (!m_codeBlock->usesArguments()) 498 return; 499 500 int argumentsRegister = m_codeBlock->argumentsRegister(); 501 int unmodifiedArgumentsRegister = JSC::unmodifiedArgumentsRegister(argumentsRegister); 502 503 prependComment("unmodified arguments"); 504 emitInitLazyRegister(®isterFor(unmodifiedArgumentsRegister)); 505 prependComment("arguments"); 506 emitInitLazyRegister(®isterFor(argumentsRegister)); 507 508 if ((m_codeBlock->usesArguments() && m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) { 509 emitOpcode(op_create_arguments); 510 instructions().append(m_codeBlock->argumentsRegister()); 511 } 512 } 513 514 void BytecodeGenerator::initActivationVar() 515 { 516 if (!m_codeBlock->needsFullScopeChain()) 517 return; 518 519 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 520 521 emitInitLazyRegister(m_activationRegister); 522 523 bool canLazilyCreateFunctions = !node->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks; 524 if (canLazilyCreateFunctions) 525 return; 526 527 emitOpcode(op_create_activation); 528 instructions().append(m_activationRegister->index()); 529 } 530 531 void BytecodeGenerator::initThisParameter() 532 { 533 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 534 535 if (isConstructor()) { 536 prependComment("'this' because we are a Constructor function"); 537 emitOpcode(op_create_this); 538 instructions().append(m_thisRegister.index()); 539 } else if (!m_codeBlock->isStrictMode() && (node->usesThis() || m_codeBlock->usesEval() || m_shouldEmitDebugHooks)) { 540 ValueProfile* profile = emitProfiledOpcode(op_convert_this); 541 instructions().append(m_thisRegister.index()); 542 instructions().append(profile); 543 } 544 } 545 546 void BytecodeGenerator::initFunctionDeclarations() 547 { 548 FunctionBodyNode* node = static_cast<FunctionBodyNode*>(m_scopeNode); 549 550 const DeclarationStacks::FunctionStack& functionStack = node->functionStack(); 551 bool canLazilyCreateFunctions = !node->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks; 552 for (size_t i = 0; i < functionStack.size(); ++i) { 553 FunctionBodyNode* function = functionStack[i].node; 554 const Identifier& ident = function->ident(); 555 RegisterID* reg = ®isterFor(symbolTable().get(ident.impl()).getIndex()); 556 if (node->captures(ident) || ident == propertyNames().arguments || !canLazilyCreateFunctions) 557 emitNewFunction(reg, function); 558 else { 559 emitInitLazyRegister(reg); 560 m_lazyFunctions.set(reg->index(), function); 561 } 341 562 } 342 563 } … … 360 581 , m_nextConstantOffset(0) 361 582 , m_globalConstantIndex(0) 362 , m_hasCreatedActivation(false)363 , m_firstLazyFunction(0)364 , m_lastLazyFunction(0)365 583 , m_globalData(scope->globalData()) 366 584 , m_lastOpcodeID(op_end) … … 377 595 378 596 codeBlock->setGlobalData(m_globalData); 379 380 prependComment("entering Function block"); 597 598 allocateArgumentsVars(); 599 allocateActivationVar(); 600 allocateCalleeVarUndeclared(); 601 allocateCapturedVars(); 602 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 603 allocateUncapturedVars(); 604 if (m_shouldEmitDebugHooks) // FIXME: What about eval? 605 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 606 preserveLastVar(); 607 608 declareParameters(); // Parameters lose to functions 609 declareCallee(); // Callee loses to everything 610 381 611 emitOpcode(op_enter); 382 if (m_codeBlock->needsFullScopeChain()) { 383 m_activationRegister = addVar(); 384 prependComment("activation for Full Scope Chain"); 385 emitInitLazyRegister(m_activationRegister); 386 m_codeBlock->setActivationRegister(m_activationRegister->index()); 387 } 388 389 // Both op_tear_off_activation and op_tear_off_arguments tear off the 'arguments' 390 // object, if created. 391 if (m_codeBlock->needsFullScopeChain() || functionBody->usesArguments()) { 392 RegisterID* unmodifiedArgumentsRegister = addVar(); // Anonymous, so it can't be modified by user code. 393 RegisterID* argumentsRegister = addVar(propertyNames().arguments, false); // Can be changed by assigning to 'arguments'. 394 395 // We can save a little space by hard-coding the knowledge that the two 396 // 'arguments' values are stored in consecutive registers, and storing 397 // only the index of the assignable one. 398 codeBlock->setArgumentsRegister(argumentsRegister->index()); 399 ASSERT_UNUSED(unmodifiedArgumentsRegister, unmodifiedArgumentsRegister->index() == JSC::unmodifiedArgumentsRegister(codeBlock->argumentsRegister())); 400 401 prependComment("arguments for Full Scope Chain"); 402 emitInitLazyRegister(argumentsRegister); 403 prependComment("unmodified arguments for Full Scope Chain"); 404 emitInitLazyRegister(unmodifiedArgumentsRegister); 405 406 if (m_codeBlock->isStrictMode()) { 407 prependComment("create arguments for strict mode"); 408 emitOpcode(op_create_arguments); 409 instructions().append(argumentsRegister->index()); 410 } 411 412 // The debugger currently retrieves the arguments object from an activation rather than pulling 413 // it from a call frame. In the long-term it should stop doing that (<rdar://problem/6911886>), 414 // but for now we force eager creation of the arguments object when debugging. 415 if (m_shouldEmitDebugHooks) { 416 prependComment("create arguments for debug hooks"); 417 emitOpcode(op_create_arguments); 418 instructions().append(argumentsRegister->index()); 419 } 420 } 421 422 RegisterID* calleeRegister = resolveCallee(functionBody); // May push to the scope chain and/or add a captured var. 423 424 const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack(); 425 const DeclarationStacks::VarStack& varStack = functionBody->varStack(); 426 427 // Captured variables and functions go first so that activations don't have 428 // to step over the non-captured locals to mark them. 429 m_hasCreatedActivation = false; 430 if (functionBody->hasCapturedVariables()) { 431 for (size_t i = 0; i < functionStack.size(); ++i) { 432 FunctionBodyNode* function = functionStack[i]; 433 const Identifier& ident = function->ident(); 434 if (functionBody->captures(ident)) { 435 if (!m_hasCreatedActivation) { 436 m_hasCreatedActivation = true; 437 prependComment("activation for captured vars"); 438 emitOpcode(op_create_activation); 439 instructions().append(m_activationRegister->index()); 440 } 441 m_functions.add(ident.impl()); 442 prependComment("captured function var"); 443 emitNewFunction(addVar(ident, false), function); 444 } 445 } 446 for (size_t i = 0; i < varStack.size(); ++i) { 447 const Identifier& ident = *varStack[i].first; 448 if (functionBody->captures(ident)) 449 addVar(ident, varStack[i].second & DeclarationStacks::IsConstant); 450 } 451 } 452 bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks; 453 if (!canLazilyCreateFunctions && !m_hasCreatedActivation) { 454 m_hasCreatedActivation = true; 455 prependComment("cannot lazily create functions"); 456 emitOpcode(op_create_activation); 457 instructions().append(m_activationRegister->index()); 458 } 459 460 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 461 462 m_firstLazyFunction = codeBlock->m_numVars; 463 for (size_t i = 0; i < functionStack.size(); ++i) { 464 FunctionBodyNode* function = functionStack[i]; 465 const Identifier& ident = function->ident(); 466 if (!functionBody->captures(ident)) { 467 m_functions.add(ident.impl()); 468 RefPtr<RegisterID> reg = addVar(ident, false); 469 // Don't lazily create functions that override the name 'arguments' 470 // as this would complicate lazy instantiation of actual arguments. 471 prependComment("a function that override 'arguments'"); 472 if (!canLazilyCreateFunctions || ident == propertyNames().arguments) 473 emitNewFunction(reg.get(), function); 474 else { 475 emitInitLazyRegister(reg.get()); 476 m_lazyFunctions.set(reg->index(), function); 477 } 478 } 479 } 480 m_lastLazyFunction = canLazilyCreateFunctions ? codeBlock->m_numVars : m_firstLazyFunction; 481 for (size_t i = 0; i < varStack.size(); ++i) { 482 const Identifier& ident = *varStack[i].first; 483 if (!functionBody->captures(ident)) 484 addVar(ident, varStack[i].second & DeclarationStacks::IsConstant); 485 } 486 487 if (m_shouldEmitDebugHooks) 488 codeBlock->m_numCapturedVars = codeBlock->m_numVars; 489 490 FunctionParameters& parameters = *functionBody->parameters(); 491 m_parameters.grow(parameters.size() + 1); // reserve space for "this" 492 493 // Add "this" as a parameter 494 int nextParameterIndex = CallFrame::thisArgumentOffset(); 495 m_thisRegister.setIndex(nextParameterIndex--); 496 m_codeBlock->addParameter(); 497 498 for (size_t i = 0; i < parameters.size(); ++i) 499 addParameter(parameters[i], nextParameterIndex--); 500 501 preserveLastVar(); 502 503 // We declare the callee's name last because it should lose to a var, function, and/or parameter declaration. 504 addCallee(functionBody, calleeRegister); 505 506 if (isConstructor()) { 507 prependComment("'this' because we are a Constructor function"); 508 emitOpcode(op_create_this); 509 instructions().append(m_thisRegister.index()); 510 } else if (!codeBlock->isStrictMode() && (functionBody->usesThis() || codeBlock->usesEval() || m_shouldEmitDebugHooks)) { 511 ValueProfile* profile = emitProfiledOpcode(op_convert_this); 512 instructions().append(m_thisRegister.index()); 513 instructions().append(profile); 514 } 612 initArgumentsVars(); 613 initActivationVar(); 614 initCalleeVar(); 615 initThisParameter(); 616 initFunctionDeclarations(); 515 617 } 516 618 … … 533 635 , m_nextConstantOffset(0) 534 636 , m_globalConstantIndex(0) 535 , m_hasCreatedActivation(true)536 , m_firstLazyFunction(0)537 , m_lastLazyFunction(0)538 637 , m_globalData(scope->globalData()) 539 638 , m_lastOpcodeID(op_end) … … 556 655 const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack(); 557 656 for (size_t i = 0; i < functionStack.size(); ++i) 558 m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i] ));657 m_codeBlock->addFunctionDecl(FunctionExecutable::create(*m_globalData, functionStack[i].node)); 559 658 560 659 const DeclarationStacks::VarStack& varStack = evalNode->varStack(); … … 563 662 variables.reserveCapacity(numVariables); 564 663 for (size_t i = 0; i < numVariables; ++i) 565 variables.append(*varStack[i]. first);664 variables.append(*varStack[i].name); 566 665 codeBlock->adoptVariables(variables); 567 666 codeBlock->m_numCapturedVars = codeBlock->m_numVars; … … 581 680 } 582 681 583 RegisterID* BytecodeGenerator::resolveCallee(FunctionBodyNode* functionBodyNode) 584 { 585 if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope()) 586 return 0; 587 588 m_calleeRegister.setIndex(RegisterFile::Callee); 589 590 // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. 591 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) { 592 emitOpcode(op_push_name_scope); 593 instructions().append(addConstant(functionBodyNode->ident())); 594 instructions().append(m_calleeRegister.index()); 595 instructions().append(ReadOnly | DontDelete); 596 597 // Put a mirror object in compilation scope, so compile-time variable resolution sees the property name we'll see at runtime. 598 m_scope.set(*globalData(), 599 JSNameScope::create( 600 m_scope->globalObject()->globalExec(), 601 functionBodyNode->ident(), 602 jsUndefined(), 603 ReadOnly | DontDelete, 604 m_scope.get() 605 ) 606 ); 607 return 0; 608 } 609 610 if (!functionBodyNode->captures(functionBodyNode->ident())) 611 return &m_calleeRegister; 612 613 // Move the callee into the captured section of the stack. 614 return emitMove(addVar(), &m_calleeRegister); 615 } 616 617 void BytecodeGenerator::addCallee(FunctionBodyNode* functionBodyNode, RegisterID* calleeRegister) 618 { 619 if (functionBodyNode->ident().isNull() || !functionBodyNode->functionNameIsInScope()) 620 return; 621 622 // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. 623 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) 624 return; 625 626 ASSERT(calleeRegister); 627 symbolTable().add(functionBodyNode->ident().impl(), SymbolTableEntry(calleeRegister->index(), ReadOnly)); 628 } 629 630 void BytecodeGenerator::addParameter(const Identifier& ident, int parameterIndex) 682 void BytecodeGenerator::declareParameter(const Identifier& ident, int parameterIndex) 631 683 { 632 684 // Parameters overwrite var declarations, but not function declarations. … … 672 724 RegisterID* BytecodeGenerator::createLazyRegisterIfNecessary(RegisterID* reg) 673 725 { 674 if (m_lastLazyFunction <= reg->index() || reg->index() < m_firstLazyFunction) 726 FunctionBodyNode* node = m_lazyFunctions.get(reg->index()); 727 if (!node) 675 728 return reg; 676 emitLazyNewFunction(reg, m_lazyFunctions.get(reg->index())); 729 730 emitLazyNewFunction(reg, node); 677 731 return reg; 678 732 } … … 1950 2004 void BytecodeGenerator::createActivationIfNecessary() 1951 2005 { 1952 if (m_hasCreatedActivation) 1953 return; 1954 if (!m_codeBlock->needsFullScopeChain()) 2006 if (!m_codeBlock->needsFullScopeChain() || m_codeType != FunctionCode) 1955 2007 return; 1956 2008 emitOpcode(op_create_activation); -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r127810 r127939 615 615 enum ConstantMode { IsConstant, IsVariable }; 616 616 enum FunctionMode { IsFunctionToSpecialize, NotFunctionOrNotSpecializable }; 617 enum VarType { Captured, NotCaptured }; 617 618 int addGlobalVar(const Identifier&, ConstantMode, FunctionMode); 618 619 void addParameter(const Identifier&, int parameterIndex); 620 RegisterID* resolveCallee(FunctionBodyNode*); 621 void addCallee(FunctionBodyNode*, RegisterID*); 619 void declareParameter(const Identifier&, int parameterIndex); 620 621 void allocateCapturedVars(); 622 void allocateUncapturedVars(); 623 void allocateActivationVar(); 624 void allocateArgumentsVars(); 625 void allocateCalleeVarUndeclared(); 626 void declareParameters(); 627 void declareCallee(); 628 void initCalleeVar(); 629 void initArgumentsVars(); 630 void initActivationVar(); 631 void initThisParameter(); 632 void initFunctionDeclarations(); 622 633 623 634 void preserveLastVar(); … … 739 750 int m_globalVarStorageOffset; 740 751 741 bool m_hasCreatedActivation;742 int m_firstLazyFunction;743 int m_lastLazyFunction;744 752 HashMap<unsigned int, FunctionBodyNode*, WTF::IntHash<unsigned int>, WTF::UnsignedWithZeroKeyHashTraits<unsigned int> > m_lazyFunctions; 745 753 typedef HashMap<FunctionBodyNode*, unsigned> FunctionOffsetMap;
Note:
See TracChangeset
for help on using the changeset viewer.