Changeset 279448 in webkit for trunk/Source/JavaScriptCore/bytecompiler
- Timestamp:
- Jun 30, 2021, 7:12:20 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r279447 r279448 153 153 return ParserError(ParserError::OutOfMemory); 154 154 155 m_codeBlock->setThisRegister(m_thisRegister.virtualRegister()); 156 157 emitLogShadowChickenPrologueIfNecessary(); 158 159 // If we have declared a variable named "arguments" and we are using arguments then we should 160 // perform that assignment now. 161 if (m_needToInitializeArguments) 162 initializeVariable(variable(propertyNames().arguments), m_argumentsRegister); 163 164 if (m_restParameter) 165 m_restParameter->emit(*this); 166 167 { 168 RefPtr<RegisterID> temp = newTemporary(); 169 RefPtr<RegisterID> tolLevelScope; 170 for (auto functionPair : m_functionsToInitialize) { 171 FunctionMetadataNode* metadata = functionPair.first; 172 FunctionVariableType functionType = functionPair.second; 173 emitNewFunction(temp.get(), metadata); 174 if (functionType == NormalFunctionVariable) 175 initializeVariable(variable(metadata->ident()), temp.get()); 176 else if (functionType == TopLevelFunctionVariable) { 177 if (!tolLevelScope) { 178 // We know this will resolve to the top level scope or global object because our parser/global initialization code 179 // doesn't allow let/const/class variables to have the same names as functions. 180 // This is a top level function, and it's an error to ever create a top level function 181 // name that would resolve to a lexical variable. E.g: 182 // ``` 183 // function f() { 184 // { 185 // let x; 186 // { 187 // //// error thrown here 188 // eval("function x(){}"); 189 // } 190 // } 191 // } 192 // ``` 193 // Therefore, we're guaranteed to have this resolve to a top level variable. 194 RefPtr<RegisterID> tolLevelObjectScope = emitResolveScope(nullptr, Variable(metadata->ident())); 195 tolLevelScope = newBlockScopeVariable(); 196 move(tolLevelScope.get(), tolLevelObjectScope.get()); 197 } 198 emitPutToScope(tolLevelScope.get(), Variable(metadata->ident()), temp.get(), ThrowIfNotFound, InitializationMode::NotInitialization); 199 } else 200 RELEASE_ASSERT_NOT_REACHED(); 201 } 202 } 203 204 bool callingClassConstructor = false; 155 bool callingNonCallableConstructor = false; 205 156 switch (constructorKind()) { 206 157 case ConstructorKind::None: 158 break; 207 159 case ConstructorKind::Naked: 208 break;209 160 case ConstructorKind::Base: 210 161 case ConstructorKind::Extends: 211 calling ClassConstructor = !isConstructor();162 callingNonCallableConstructor = !isConstructor(); 212 163 break; 213 164 } 214 if (!callingClassConstructor) 165 166 m_codeBlock->setThisRegister(m_thisRegister.virtualRegister()); 167 168 emitLogShadowChickenPrologueIfNecessary(); 169 170 if (!callingNonCallableConstructor) { 171 // If we have declared a variable named "arguments" and we are using arguments then we should 172 // perform that assignment now. 173 if (m_needToInitializeArguments) 174 initializeVariable(variable(propertyNames().arguments), m_argumentsRegister); 175 176 if (m_restParameter) 177 m_restParameter->emit(*this); 178 179 { 180 RefPtr<RegisterID> temp = newTemporary(); 181 RefPtr<RegisterID> tolLevelScope; 182 for (auto functionPair : m_functionsToInitialize) { 183 FunctionMetadataNode* metadata = functionPair.first; 184 FunctionVariableType functionType = functionPair.second; 185 emitNewFunction(temp.get(), metadata); 186 if (functionType == NormalFunctionVariable) 187 initializeVariable(variable(metadata->ident()), temp.get()); 188 else if (functionType == TopLevelFunctionVariable) { 189 if (!tolLevelScope) { 190 // We know this will resolve to the top level scope or global object because our parser/global initialization code 191 // doesn't allow let/const/class variables to have the same names as functions. 192 // This is a top level function, and it's an error to ever create a top level function 193 // name that would resolve to a lexical variable. E.g: 194 // ``` 195 // function f() { 196 // { 197 // let x; 198 // { 199 // //// error thrown here 200 // eval("function x(){}"); 201 // } 202 // } 203 // } 204 // ``` 205 // Therefore, we're guaranteed to have this resolve to a top level variable. 206 RefPtr<RegisterID> tolLevelObjectScope = emitResolveScope(nullptr, Variable(metadata->ident())); 207 tolLevelScope = newBlockScopeVariable(); 208 move(tolLevelScope.get(), tolLevelObjectScope.get()); 209 } 210 emitPutToScope(tolLevelScope.get(), Variable(metadata->ident()), temp.get(), ThrowIfNotFound, InitializationMode::NotInitialization); 211 } else 212 RELEASE_ASSERT_NOT_REACHED(); 213 } 214 } 215 215 216 m_scopeNode->emitBytecode(*this); 216 else {217 } else { 217 218 // At this point we would have emitted an unconditional throw followed by some nonsense that's 218 219 // just an artifact of how this generator is structured. That code never runs, but it confuses … … 442 443 443 444 emitCheckTraps(); 445 446 switch (constructorKind()) { 447 case ConstructorKind::None: 448 break; 449 case ConstructorKind::Naked: 450 if (!isConstructor()) { 451 emitThrowTypeError("Cannot call a constructor without |new|"); 452 return; 453 } 454 break; 455 case ConstructorKind::Base: 456 case ConstructorKind::Extends: 457 if (!isConstructor()) { 458 emitThrowTypeError("Cannot call a class constructor without |new|"); 459 return; 460 } 461 break; 462 } 444 463 445 464 if (functionNameIsInScope(functionNode->ident(), functionNode->functionMode())) { … … 700 719 } 701 720 721 case SourceParseMode::ArrowFunctionMode: 722 break; 723 702 724 default: { 703 if (SourceParseMode::ArrowFunctionMode != parseMode) { 704 if (isConstructor()) { 705 if (m_newTargetRegister) 706 move(m_newTargetRegister, &m_thisRegister); 707 switch (constructorKind()) { 708 case ConstructorKind::Naked: 709 // Naked constructor not create |this| automatically. 710 break; 711 case ConstructorKind::None: 712 case ConstructorKind::Base: 713 emitCreateThis(&m_thisRegister); 714 if (Options::usePrivateMethods() && privateBrandRequirement() == PrivateBrandRequirement::Needed) 715 emitInstallPrivateBrand(&m_thisRegister); 716 717 emitInstanceFieldInitializationIfNeeded(&m_thisRegister, &m_calleeRegister, m_scopeNode->position(), m_scopeNode->position(), m_scopeNode->position()); 718 break; 719 case ConstructorKind::Extends: 720 moveEmptyValue(&m_thisRegister); 721 break; 725 if (isConstructor()) { 726 if (m_newTargetRegister) 727 move(m_newTargetRegister, &m_thisRegister); 728 switch (constructorKind()) { 729 case ConstructorKind::Naked: 730 // Naked constructor not create |this| automatically. 731 break; 732 case ConstructorKind::None: 733 case ConstructorKind::Base: 734 emitCreateThis(&m_thisRegister); 735 if (Options::usePrivateMethods() && privateBrandRequirement() == PrivateBrandRequirement::Needed) 736 emitInstallPrivateBrand(&m_thisRegister); 737 738 emitInstanceFieldInitializationIfNeeded(&m_thisRegister, &m_calleeRegister, m_scopeNode->position(), m_scopeNode->position(), m_scopeNode->position()); 739 break; 740 case ConstructorKind::Extends: 741 moveEmptyValue(&m_thisRegister); 742 break; 743 } 744 } else { 745 switch (constructorKind()) { 746 case ConstructorKind::None: { 747 bool shouldEmitToThis = false; 748 if (functionNode->usesThis() || usesEval() || m_scopeNode->doAnyInnerArrowFunctionsUseThis() || m_scopeNode->doAnyInnerArrowFunctionsUseEval()) 749 shouldEmitToThis = true; 750 else if ((functionNode->usesSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty()) && !ecmaMode.isStrict()) { 751 // We must emit to_this when we're not in strict mode because we 752 // will convert |this| to an object, and that object may be passed 753 // to a strict function as |this|. This is observable because that 754 // strict function's to_this will just return the object. 755 // 756 // We don't need to emit this for strict-mode code because 757 // strict-mode code may call another strict function, which will 758 // to_this if it directly uses this; this is OK, because we defer 759 // to_this until |this| is used directly. Strict-mode code might 760 // also call a sloppy mode function, and that will to_this, which 761 // will defer the conversion, again, until necessary. 762 shouldEmitToThis = true; 722 763 } 723 } else { 724 switch (constructorKind()) { 725 case ConstructorKind::None: { 726 bool shouldEmitToThis = false; 727 if (functionNode->usesThis() || usesEval() || m_scopeNode->doAnyInnerArrowFunctionsUseThis() || m_scopeNode->doAnyInnerArrowFunctionsUseEval()) 728 shouldEmitToThis = true; 729 else if ((functionNode->usesSuperProperty() || m_scopeNode->doAnyInnerArrowFunctionsUseSuperProperty()) && !ecmaMode.isStrict()) { 730 // We must emit to_this when we're not in strict mode because we 731 // will convert |this| to an object, and that object may be passed 732 // to a strict function as |this|. This is observable because that 733 // strict function's to_this will just return the object. 734 // 735 // We don't need to emit this for strict-mode code because 736 // strict-mode code may call another strict function, which will 737 // to_this if it directly uses this; this is OK, because we defer 738 // to_this until |this| is used directly. Strict-mode code might 739 // also call a sloppy mode function, and that will to_this, which 740 // will defer the conversion, again, until necessary. 741 shouldEmitToThis = true; 742 } 743 744 if (shouldEmitToThis) 745 emitToThis(); 746 break; 747 } 748 case ConstructorKind::Naked: 749 emitThrowTypeError("Cannot call a constructor without |new|"); 750 break; 751 case ConstructorKind::Base: 752 case ConstructorKind::Extends: 753 emitThrowTypeError("Cannot call a class constructor without |new|"); 754 break; 755 } 764 765 if (shouldEmitToThis) 766 emitToThis(); 767 break; 768 } 769 case ConstructorKind::Naked: 770 case ConstructorKind::Base: 771 case ConstructorKind::Extends: 772 RELEASE_ASSERT_NOT_REACHED(); 773 break; 756 774 } 757 775 }
Note:
See TracChangeset
for help on using the changeset viewer.