Changeset 208063 in webkit for trunk/Source/JavaScriptCore/runtime/NativeExecutable.cpp
- Timestamp:
- Oct 28, 2016, 1:04:56 PM (9 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/runtime/NativeExecutable.cpp
r207790 r208063 25 25 26 26 #include "config.h" 27 #include "Executable.h"28 27 29 28 #include "BatchedTransitionOptimizer.h" … … 32 31 #include "JIT.h" 33 32 #include "JSCInlines.h" 34 #include "JSWasmModule.h"35 33 #include "LLIntEntrypoint.h" 36 34 #include "Parser.h" … … 40 38 41 39 namespace JSC { 42 43 const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };44 45 void ExecutableBase::destroy(JSCell* cell)46 {47 static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();48 }49 50 void ExecutableBase::clearCode()51 {52 #if ENABLE(JIT)53 m_jitCodeForCall = nullptr;54 m_jitCodeForConstruct = nullptr;55 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();56 m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();57 #endif58 m_numParametersForCall = NUM_PARAMETERS_NOT_COMPILED;59 m_numParametersForConstruct = NUM_PARAMETERS_NOT_COMPILED;60 61 if (classInfo() == FunctionExecutable::info()) {62 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);63 executable->m_codeBlockForCall.clear();64 executable->m_codeBlockForConstruct.clear();65 return;66 }67 68 if (classInfo() == EvalExecutable::info()) {69 EvalExecutable* executable = jsCast<EvalExecutable*>(this);70 executable->m_evalCodeBlock.clear();71 executable->m_unlinkedEvalCodeBlock.clear();72 return;73 }74 75 if (classInfo() == ProgramExecutable::info()) {76 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);77 executable->m_programCodeBlock.clear();78 executable->m_unlinkedProgramCodeBlock.clear();79 return;80 }81 82 if (classInfo() == ModuleProgramExecutable::info()) {83 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);84 executable->m_moduleProgramCodeBlock.clear();85 executable->m_unlinkedModuleProgramCodeBlock.clear();86 executable->m_moduleEnvironmentSymbolTable.clear();87 return;88 }89 90 #if ENABLE(WEBASSEMBLY)91 if (classInfo() == WebAssemblyExecutable::info()) {92 WebAssemblyExecutable* executable = jsCast<WebAssemblyExecutable*>(this);93 executable->m_codeBlockForCall.clear();94 return;95 }96 #endif97 98 ASSERT(classInfo() == NativeExecutable::info());99 }100 40 101 41 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(NativeExecutable) }; … … 136 76 } 137 77 138 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(ScriptExecutable) };139 140 ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isInArrowFunctionContext, EvalContextType evalContextType, Intrinsic intrinsic)141 : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED, intrinsic)142 , m_features(isInStrictContext ? StrictModeFeature : 0)143 , m_didTryToEnterInLoop(false)144 , m_hasCapturedVariables(false)145 , m_neverInline(false)146 , m_neverOptimize(false)147 , m_neverFTLOptimize(false)148 , m_isArrowFunctionContext(isInArrowFunctionContext)149 , m_canUseOSRExitFuzzing(true)150 , m_derivedContextType(static_cast<unsigned>(derivedContextType))151 , m_evalContextType(static_cast<unsigned>(evalContextType))152 , m_overrideLineNumber(-1)153 , m_firstLine(-1)154 , m_lastLine(-1)155 , m_startColumn(UINT_MAX)156 , m_endColumn(UINT_MAX)157 , m_typeProfilingStartOffset(UINT_MAX)158 , m_typeProfilingEndOffset(UINT_MAX)159 , m_source(source)160 {161 }162 163 void ScriptExecutable::destroy(JSCell* cell)164 {165 static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();166 }167 168 void ScriptExecutable::installCode(CodeBlock* codeBlock)169 {170 installCode(*codeBlock->vm(), codeBlock, codeBlock->codeType(), codeBlock->specializationKind());171 }172 173 void ScriptExecutable::installCode(VM& vm, CodeBlock* genericCodeBlock, CodeType codeType, CodeSpecializationKind kind)174 {175 ASSERT(vm.heap.isDeferred());176 177 if (genericCodeBlock)178 CODEBLOCK_LOG_EVENT(genericCodeBlock, "installCode", ());179 180 CodeBlock* oldCodeBlock = nullptr;181 182 switch (codeType) {183 case GlobalCode: {184 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);185 ProgramCodeBlock* codeBlock = static_cast<ProgramCodeBlock*>(genericCodeBlock);186 187 ASSERT(kind == CodeForCall);188 189 oldCodeBlock = executable->m_programCodeBlock.get();190 executable->m_programCodeBlock.setMayBeNull(vm, this, codeBlock);191 break;192 }193 194 case ModuleCode: {195 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);196 ModuleProgramCodeBlock* codeBlock = static_cast<ModuleProgramCodeBlock*>(genericCodeBlock);197 198 ASSERT(kind == CodeForCall);199 200 oldCodeBlock = executable->m_moduleProgramCodeBlock.get();201 executable->m_moduleProgramCodeBlock.setMayBeNull(vm, this, codeBlock);202 break;203 }204 205 case EvalCode: {206 EvalExecutable* executable = jsCast<EvalExecutable*>(this);207 EvalCodeBlock* codeBlock = static_cast<EvalCodeBlock*>(genericCodeBlock);208 209 ASSERT(kind == CodeForCall);210 211 oldCodeBlock = executable->m_evalCodeBlock.get();212 executable->m_evalCodeBlock.setMayBeNull(vm, this, codeBlock);213 break;214 }215 216 case FunctionCode: {217 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);218 FunctionCodeBlock* codeBlock = static_cast<FunctionCodeBlock*>(genericCodeBlock);219 220 switch (kind) {221 case CodeForCall:222 oldCodeBlock = executable->m_codeBlockForCall.get();223 executable->m_codeBlockForCall.setMayBeNull(vm, this, codeBlock);224 break;225 case CodeForConstruct:226 oldCodeBlock = executable->m_codeBlockForConstruct.get();227 executable->m_codeBlockForConstruct.setMayBeNull(vm, this, codeBlock);228 break;229 }230 break;231 }232 }233 234 switch (kind) {235 case CodeForCall:236 m_jitCodeForCall = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;237 m_jitCodeForCallWithArityCheck = MacroAssemblerCodePtr();238 m_numParametersForCall = genericCodeBlock ? genericCodeBlock->numParameters() : NUM_PARAMETERS_NOT_COMPILED;239 break;240 case CodeForConstruct:241 m_jitCodeForConstruct = genericCodeBlock ? genericCodeBlock->jitCode() : nullptr;242 m_jitCodeForConstructWithArityCheck = MacroAssemblerCodePtr();243 m_numParametersForConstruct = genericCodeBlock ? genericCodeBlock->numParameters() : NUM_PARAMETERS_NOT_COMPILED;244 break;245 }246 247 if (genericCodeBlock) {248 RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);249 RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));250 251 if (Options::verboseOSR())252 dataLog("Installing ", *genericCodeBlock, "\n");253 254 if (vm.m_perBytecodeProfiler)255 vm.m_perBytecodeProfiler->ensureBytecodesFor(genericCodeBlock);256 257 if (Debugger* debugger = genericCodeBlock->globalObject()->debugger())258 debugger->registerCodeBlock(genericCodeBlock);259 }260 261 if (oldCodeBlock)262 oldCodeBlock->unlinkIncomingCalls();263 264 vm.heap.writeBarrier(this);265 }266 267 CodeBlock* ScriptExecutable::newCodeBlockFor(268 CodeSpecializationKind kind, JSFunction* function, JSScope* scope, JSObject*& exception)269 {270 VM* vm = scope->vm();271 auto throwScope = DECLARE_THROW_SCOPE(*vm);272 273 ASSERT(vm->heap.isDeferred());274 ASSERT(startColumn() != UINT_MAX);275 ASSERT(endColumn() != UINT_MAX);276 277 if (classInfo() == EvalExecutable::info()) {278 EvalExecutable* executable = jsCast<EvalExecutable*>(this);279 RELEASE_ASSERT(kind == CodeForCall);280 RELEASE_ASSERT(!executable->m_evalCodeBlock);281 RELEASE_ASSERT(!function);282 return EvalCodeBlock::create(vm,283 executable, executable->m_unlinkedEvalCodeBlock.get(), scope,284 executable->source().provider());285 }286 287 if (classInfo() == ProgramExecutable::info()) {288 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);289 RELEASE_ASSERT(kind == CodeForCall);290 RELEASE_ASSERT(!executable->m_programCodeBlock);291 RELEASE_ASSERT(!function);292 return ProgramCodeBlock::create(vm,293 executable, executable->m_unlinkedProgramCodeBlock.get(), scope,294 executable->source().provider(), executable->source().startColumn());295 }296 297 if (classInfo() == ModuleProgramExecutable::info()) {298 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);299 RELEASE_ASSERT(kind == CodeForCall);300 RELEASE_ASSERT(!executable->m_moduleProgramCodeBlock);301 RELEASE_ASSERT(!function);302 return ModuleProgramCodeBlock::create(vm,303 executable, executable->m_unlinkedModuleProgramCodeBlock.get(), scope,304 executable->source().provider(), executable->source().startColumn());305 }306 307 RELEASE_ASSERT(classInfo() == FunctionExecutable::info());308 RELEASE_ASSERT(function);309 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);310 RELEASE_ASSERT(!executable->codeBlockFor(kind));311 JSGlobalObject* globalObject = scope->globalObject();312 ParserError error;313 DebuggerMode debuggerMode = globalObject->hasInteractiveDebugger() ? DebuggerOn : DebuggerOff;314 UnlinkedFunctionCodeBlock* unlinkedCodeBlock =315 executable->m_unlinkedExecutable->unlinkedCodeBlockFor(316 *vm, executable->m_source, kind, debuggerMode, error,317 executable->parseMode());318 recordParse(319 executable->m_unlinkedExecutable->features(),320 executable->m_unlinkedExecutable->hasCapturedVariables(), firstLine(),321 lastLine(), startColumn(), endColumn());322 if (!unlinkedCodeBlock) {323 exception = throwException(324 globalObject->globalExec(), throwScope,325 error.toErrorObject(globalObject, executable->m_source));326 return nullptr;327 }328 329 SourceProvider* provider = executable->source().provider();330 unsigned sourceOffset = executable->source().startOffset();331 unsigned startColumn = executable->source().startColumn();332 333 return FunctionCodeBlock::create(vm,334 executable, unlinkedCodeBlock, scope, provider, sourceOffset, startColumn);335 }336 337 CodeBlock* ScriptExecutable::newReplacementCodeBlockFor(338 CodeSpecializationKind kind)339 {340 if (classInfo() == EvalExecutable::info()) {341 RELEASE_ASSERT(kind == CodeForCall);342 EvalExecutable* executable = jsCast<EvalExecutable*>(this);343 EvalCodeBlock* baseline = static_cast<EvalCodeBlock*>(344 executable->m_evalCodeBlock->baselineVersion());345 EvalCodeBlock* result = EvalCodeBlock::create(vm(),346 CodeBlock::CopyParsedBlock, *baseline);347 result->setAlternative(*vm(), baseline);348 return result;349 }350 351 if (classInfo() == ProgramExecutable::info()) {352 RELEASE_ASSERT(kind == CodeForCall);353 ProgramExecutable* executable = jsCast<ProgramExecutable*>(this);354 ProgramCodeBlock* baseline = static_cast<ProgramCodeBlock*>(355 executable->m_programCodeBlock->baselineVersion());356 ProgramCodeBlock* result = ProgramCodeBlock::create(vm(),357 CodeBlock::CopyParsedBlock, *baseline);358 result->setAlternative(*vm(), baseline);359 return result;360 }361 362 if (classInfo() == ModuleProgramExecutable::info()) {363 RELEASE_ASSERT(kind == CodeForCall);364 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(this);365 ModuleProgramCodeBlock* baseline = static_cast<ModuleProgramCodeBlock*>(366 executable->m_moduleProgramCodeBlock->baselineVersion());367 ModuleProgramCodeBlock* result = ModuleProgramCodeBlock::create(vm(),368 CodeBlock::CopyParsedBlock, *baseline);369 result->setAlternative(*vm(), baseline);370 return result;371 }372 373 RELEASE_ASSERT(classInfo() == FunctionExecutable::info());374 FunctionExecutable* executable = jsCast<FunctionExecutable*>(this);375 FunctionCodeBlock* baseline = static_cast<FunctionCodeBlock*>(376 executable->codeBlockFor(kind)->baselineVersion());377 FunctionCodeBlock* result = FunctionCodeBlock::create(vm(),378 CodeBlock::CopyParsedBlock, *baseline);379 result->setAlternative(*vm(), baseline);380 return result;381 }382 383 static void setupLLInt(VM& vm, CodeBlock* codeBlock)384 {385 LLInt::setEntrypoint(vm, codeBlock);386 }387 388 static void setupJIT(VM& vm, CodeBlock* codeBlock)389 {390 #if ENABLE(JIT)391 CompilationResult result = JIT::compile(&vm, codeBlock, JITCompilationMustSucceed);392 RELEASE_ASSERT(result == CompilationSuccessful);393 #else394 UNUSED_PARAM(vm);395 UNUSED_PARAM(codeBlock);396 UNREACHABLE_FOR_PLATFORM();397 #endif398 }399 400 JSObject* ScriptExecutable::prepareForExecutionImpl(401 VM& vm, JSFunction* function, JSScope* scope, CodeSpecializationKind kind, CodeBlock*& resultCodeBlock)402 {403 DeferGCForAWhile deferGC(vm.heap);404 405 if (vm.getAndClearFailNextNewCodeBlock())406 return createError(scope->globalObject()->globalExec(), ASCIILiteral("Forced Failure"));407 408 JSObject* exception = 0;409 CodeBlock* codeBlock = newCodeBlockFor(kind, function, scope, exception);410 resultCodeBlock = codeBlock;411 if (!codeBlock) {412 RELEASE_ASSERT(exception);413 return exception;414 }415 416 if (Options::validateBytecode())417 codeBlock->validate();418 419 if (Options::useLLInt())420 setupLLInt(vm, codeBlock);421 else422 setupJIT(vm, codeBlock);423 424 installCode(vm, codeBlock, codeBlock->codeType(), codeBlock->specializationKind());425 return nullptr;426 }427 428 const ClassInfo EvalExecutable::s_info = { "EvalExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(EvalExecutable) };429 430 EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ)431 {432 VM& vm = exec->vm();433 auto scope = DECLARE_THROW_SCOPE(vm);434 435 JSGlobalObject* globalObject = exec->lexicalGlobalObject();436 if (!globalObject->evalEnabled()) {437 throwException(exec, scope, createEvalError(exec, globalObject->evalDisabledErrorMessage()));438 return 0;439 }440 441 EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext, derivedContextType, isArrowFunctionContext, evalContextType);442 executable->finishCreation(vm);443 444 UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable, variablesUnderTDZ);445 if (!unlinkedEvalCode)446 return 0;447 448 executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode);449 450 return executable;451 }452 453 EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)454 : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext, derivedContextType, isArrowFunctionContext, evalContextType, NoIntrinsic)455 {456 ASSERT(source.provider()->sourceType() == SourceProviderSourceType::Program);457 }458 459 void EvalExecutable::destroy(JSCell* cell)460 {461 static_cast<EvalExecutable*>(cell)->EvalExecutable::~EvalExecutable();462 }463 464 const ClassInfo ProgramExecutable::s_info = { "ProgramExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(ProgramExecutable) };465 466 ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)467 : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false, DerivedContextType::None, false, EvalContextType::None, NoIntrinsic)468 {469 ASSERT(source.provider()->sourceType() == SourceProviderSourceType::Program);470 m_typeProfilingStartOffset = 0;471 m_typeProfilingEndOffset = source.length() - 1;472 if (exec->vm().typeProfiler() || exec->vm().controlFlowProfiler())473 exec->vm().functionHasExecutedCache()->insertUnexecutedRange(sourceID(), m_typeProfilingStartOffset, m_typeProfilingEndOffset);474 }475 476 void ProgramExecutable::destroy(JSCell* cell)477 {478 static_cast<ProgramExecutable*>(cell)->ProgramExecutable::~ProgramExecutable();479 }480 481 const ClassInfo ModuleProgramExecutable::s_info = { "ModuleProgramExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(ModuleProgramExecutable) };482 483 ModuleProgramExecutable::ModuleProgramExecutable(ExecState* exec, const SourceCode& source)484 : ScriptExecutable(exec->vm().moduleProgramExecutableStructure.get(), exec->vm(), source, false, DerivedContextType::None, false, EvalContextType::None, NoIntrinsic)485 {486 ASSERT(source.provider()->sourceType() == SourceProviderSourceType::Module);487 m_typeProfilingStartOffset = 0;488 m_typeProfilingEndOffset = source.length() - 1;489 if (exec->vm().typeProfiler() || exec->vm().controlFlowProfiler())490 exec->vm().functionHasExecutedCache()->insertUnexecutedRange(sourceID(), m_typeProfilingStartOffset, m_typeProfilingEndOffset);491 }492 493 ModuleProgramExecutable* ModuleProgramExecutable::create(ExecState* exec, const SourceCode& source)494 {495 JSGlobalObject* globalObject = exec->lexicalGlobalObject();496 ModuleProgramExecutable* executable = new (NotNull, allocateCell<ModuleProgramExecutable>(*exec->heap())) ModuleProgramExecutable(exec, source);497 executable->finishCreation(exec->vm());498 499 UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCode = globalObject->createModuleProgramCodeBlock(exec, executable);500 if (!unlinkedModuleProgramCode)501 return nullptr;502 executable->m_unlinkedModuleProgramCodeBlock.set(exec->vm(), executable, unlinkedModuleProgramCode);503 504 executable->m_moduleEnvironmentSymbolTable.set(exec->vm(), executable, jsCast<SymbolTable*>(unlinkedModuleProgramCode->constantRegister(unlinkedModuleProgramCode->moduleEnvironmentSymbolTableConstantRegisterOffset()).get())->cloneScopePart(exec->vm()));505 506 return executable;507 }508 509 void ModuleProgramExecutable::destroy(JSCell* cell)510 {511 static_cast<ModuleProgramExecutable*>(cell)->ModuleProgramExecutable::~ModuleProgramExecutable();512 }513 514 const ClassInfo FunctionExecutable::s_info = { "FunctionExecutable", &ScriptExecutable::s_info, 0, CREATE_METHOD_TABLE(FunctionExecutable) };515 516 FunctionExecutable::FunctionExecutable(VM& vm, const SourceCode& source, UnlinkedFunctionExecutable* unlinkedExecutable, unsigned firstLine, unsigned lastLine, unsigned startColumn, unsigned endColumn, Intrinsic intrinsic)517 : ScriptExecutable(vm.functionExecutableStructure.get(), vm, source, unlinkedExecutable->isInStrictContext(), unlinkedExecutable->derivedContextType(), false, EvalContextType::None, intrinsic)518 , m_unlinkedExecutable(vm, this, unlinkedExecutable)519 {520 RELEASE_ASSERT(!source.isNull());521 ASSERT(source.length());522 m_firstLine = firstLine;523 m_lastLine = lastLine;524 ASSERT(startColumn != UINT_MAX);525 ASSERT(endColumn != UINT_MAX);526 m_startColumn = startColumn;527 m_endColumn = endColumn;528 m_parametersStartOffset = unlinkedExecutable->parametersStartOffset();529 m_typeProfilingStartOffset = unlinkedExecutable->typeProfilingStartOffset();530 m_typeProfilingEndOffset = unlinkedExecutable->typeProfilingEndOffset();531 }532 533 void FunctionExecutable::finishCreation(VM& vm)534 {535 Base::finishCreation(vm);536 m_singletonFunction.set(vm, this, InferredValue::create(vm));537 }538 539 void FunctionExecutable::destroy(JSCell* cell)540 {541 static_cast<FunctionExecutable*>(cell)->FunctionExecutable::~FunctionExecutable();542 }543 544 inline const char* samplingDescription(JITCode::JITType jitType)545 {546 switch (jitType) {547 case JITCode::InterpreterThunk:548 return "Interpreter Compilation (TOTAL)";549 case JITCode::BaselineJIT:550 return "Baseline Compilation (TOTAL)";551 case JITCode::DFGJIT:552 return "DFG Compilation (TOTAL)";553 case JITCode::FTLJIT:554 return "FTL Compilation (TOTAL)";555 default:556 RELEASE_ASSERT_NOT_REACHED();557 return 0;558 }559 }560 561 void EvalExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)562 {563 EvalExecutable* thisObject = jsCast<EvalExecutable*>(cell);564 ASSERT_GC_OBJECT_INHERITS(thisObject, info());565 ScriptExecutable::visitChildren(thisObject, visitor);566 visitor.append(&thisObject->m_unlinkedEvalCodeBlock);567 if (thisObject->m_evalCodeBlock)568 thisObject->m_evalCodeBlock->visitWeakly(visitor);569 }570 571 JSObject* ProgramExecutable::checkSyntax(ExecState* exec)572 {573 ParserError error;574 VM* vm = &exec->vm();575 JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();576 std::unique_ptr<ProgramNode> programNode = parse<ProgramNode>(577 vm, m_source, Identifier(), JSParserBuiltinMode::NotBuiltin,578 JSParserStrictMode::NotStrict, JSParserScriptMode::Classic, SourceParseMode::ProgramMode, SuperBinding::NotNeeded, error);579 if (programNode)580 return 0;581 ASSERT(error.isValid());582 return error.toErrorObject(lexicalGlobalObject, m_source);583 }584 585 JSObject* ProgramExecutable::initializeGlobalProperties(VM& vm, CallFrame* callFrame, JSScope* scope)586 {587 RELEASE_ASSERT(scope);588 JSGlobalObject* globalObject = scope->globalObject();589 RELEASE_ASSERT(globalObject);590 ASSERT(&globalObject->vm() == &vm);591 592 JSObject* exception = 0;593 UnlinkedProgramCodeBlock* unlinkedCodeBlock = globalObject->createProgramCodeBlock(callFrame, this, &exception);594 if (exception)595 return exception;596 597 JSGlobalLexicalEnvironment* globalLexicalEnvironment = globalObject->globalLexicalEnvironment();598 const VariableEnvironment& variableDeclarations = unlinkedCodeBlock->variableDeclarations();599 const VariableEnvironment& lexicalDeclarations = unlinkedCodeBlock->lexicalDeclarations();600 // The ES6 spec says that no vars/global properties/let/const can be duplicated in the global scope.601 // This carried out section 15.1.8 of the ES6 spec: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-globaldeclarationinstantiation602 {603 ExecState* exec = globalObject->globalExec();604 // Check for intersection of "var" and "let"/"const"/"class"605 for (auto& entry : lexicalDeclarations) {606 if (variableDeclarations.contains(entry.key))607 return createSyntaxError(exec, makeString("Can't create duplicate variable: '", String(entry.key.get()), "'"));608 }609 610 // Check if any new "let"/"const"/"class" will shadow any pre-existing global property names, or "var"/"let"/"const" variables.611 // It's an error to introduce a shadow.612 for (auto& entry : lexicalDeclarations) {613 if (globalObject->hasProperty(exec, entry.key.get())) {614 // The ES6 spec says that just RestrictedGlobalProperty can't be shadowed615 // This carried out section 8.1.1.4.14 of the ES6 spec: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-hasrestrictedglobalproperty616 PropertyDescriptor descriptor;617 globalObject->getOwnPropertyDescriptor(exec, entry.key.get(), descriptor);618 619 if (descriptor.value() != jsUndefined() && !descriptor.configurable())620 return createSyntaxError(exec, makeString("Can't create duplicate variable that shadows a global property: '", String(entry.key.get()), "'"));621 }622 623 if (globalLexicalEnvironment->hasProperty(exec, entry.key.get())) {624 if (UNLIKELY(entry.value.isConst() && !vm.globalConstRedeclarationShouldThrow() && !isStrictMode())) {625 // We only allow "const" duplicate declarations under this setting.626 // For example, we don't "let" variables to be overridden by "const" variables.627 if (globalLexicalEnvironment->isConstVariable(entry.key.get()))628 continue;629 }630 return createSyntaxError(exec, makeString("Can't create duplicate variable: '", String(entry.key.get()), "'"));631 }632 }633 634 // Check if any new "var"s will shadow any previous "let"/"const"/"class" names.635 // It's an error to introduce a shadow.636 if (!globalLexicalEnvironment->isEmpty()) {637 for (auto& entry : variableDeclarations) {638 if (globalLexicalEnvironment->hasProperty(exec, entry.key.get()))639 return createSyntaxError(exec, makeString("Can't create duplicate variable: '", String(entry.key.get()), "'"));640 }641 }642 }643 644 645 m_unlinkedProgramCodeBlock.set(vm, this, unlinkedCodeBlock);646 647 BatchedTransitionOptimizer optimizer(vm, globalObject);648 649 for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {650 UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);651 ASSERT(!unlinkedFunctionExecutable->name().isEmpty());652 globalObject->addFunction(callFrame, unlinkedFunctionExecutable->name());653 if (vm.typeProfiler() || vm.controlFlowProfiler()) {654 vm.functionHasExecutedCache()->insertUnexecutedRange(sourceID(),655 unlinkedFunctionExecutable->typeProfilingStartOffset(),656 unlinkedFunctionExecutable->typeProfilingEndOffset());657 }658 }659 660 for (auto& entry : variableDeclarations) {661 ASSERT(entry.value.isVar());662 globalObject->addVar(callFrame, Identifier::fromUid(&vm, entry.key.get()));663 }664 665 {666 JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(globalObject->globalScope());667 SymbolTable* symbolTable = globalLexicalEnvironment->symbolTable();668 ConcurrentJITLocker locker(symbolTable->m_lock);669 for (auto& entry : lexicalDeclarations) {670 if (UNLIKELY(entry.value.isConst() && !vm.globalConstRedeclarationShouldThrow() && !isStrictMode())) {671 if (symbolTable->contains(locker, entry.key.get()))672 continue;673 }674 ScopeOffset offset = symbolTable->takeNextScopeOffset(locker);675 SymbolTableEntry newEntry(VarOffset(offset), entry.value.isConst() ? ReadOnly : 0);676 newEntry.prepareToWatch();677 symbolTable->add(locker, entry.key.get(), newEntry);678 679 ScopeOffset offsetForAssert = globalLexicalEnvironment->addVariables(1, jsTDZValue());680 RELEASE_ASSERT(offsetForAssert == offset);681 }682 }683 return 0;684 }685 686 void ProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)687 {688 ProgramExecutable* thisObject = jsCast<ProgramExecutable*>(cell);689 ASSERT_GC_OBJECT_INHERITS(thisObject, info());690 ScriptExecutable::visitChildren(thisObject, visitor);691 visitor.append(&thisObject->m_unlinkedProgramCodeBlock);692 if (thisObject->m_programCodeBlock)693 thisObject->m_programCodeBlock->visitWeakly(visitor);694 }695 696 void ModuleProgramExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)697 {698 ModuleProgramExecutable* thisObject = jsCast<ModuleProgramExecutable*>(cell);699 ASSERT_GC_OBJECT_INHERITS(thisObject, info());700 ScriptExecutable::visitChildren(thisObject, visitor);701 visitor.append(&thisObject->m_unlinkedModuleProgramCodeBlock);702 visitor.append(&thisObject->m_moduleEnvironmentSymbolTable);703 if (thisObject->m_moduleProgramCodeBlock)704 thisObject->m_moduleProgramCodeBlock->visitWeakly(visitor);705 }706 707 FunctionCodeBlock* FunctionExecutable::baselineCodeBlockFor(CodeSpecializationKind kind)708 {709 FunctionCodeBlock* result;710 if (kind == CodeForCall)711 result = m_codeBlockForCall.get();712 else {713 RELEASE_ASSERT(kind == CodeForConstruct);714 result = m_codeBlockForConstruct.get();715 }716 if (!result)717 return 0;718 return static_cast<FunctionCodeBlock*>(result->baselineAlternative());719 }720 721 void FunctionExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)722 {723 FunctionExecutable* thisObject = jsCast<FunctionExecutable*>(cell);724 ASSERT_GC_OBJECT_INHERITS(thisObject, info());725 ScriptExecutable::visitChildren(thisObject, visitor);726 if (thisObject->m_codeBlockForCall)727 thisObject->m_codeBlockForCall->visitWeakly(visitor);728 if (thisObject->m_codeBlockForConstruct)729 thisObject->m_codeBlockForConstruct->visitWeakly(visitor);730 visitor.append(&thisObject->m_unlinkedExecutable);731 visitor.append(&thisObject->m_singletonFunction);732 }733 734 FunctionExecutable* FunctionExecutable::fromGlobalCode(735 const Identifier& name, ExecState& exec, const SourceCode& source,736 JSObject*& exception, int overrideLineNumber)737 {738 UnlinkedFunctionExecutable* unlinkedExecutable =739 UnlinkedFunctionExecutable::fromGlobalCode(740 name, exec, source, exception, overrideLineNumber);741 if (!unlinkedExecutable)742 return nullptr;743 744 return unlinkedExecutable->link(exec.vm(), source, overrideLineNumber);745 }746 747 #if ENABLE(WEBASSEMBLY)748 const ClassInfo WebAssemblyExecutable::s_info = { "WebAssemblyExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(WebAssemblyExecutable) };749 750 WebAssemblyExecutable::WebAssemblyExecutable(VM& vm, const SourceCode& source, JSWasmModule* module, unsigned functionIndex)751 : ExecutableBase(vm, vm.webAssemblyExecutableStructure.get(), NUM_PARAMETERS_NOT_COMPILED, NoIntrinsic)752 , m_source(source)753 , m_module(vm, this, module)754 , m_functionIndex(functionIndex)755 {756 ASSERT(source.provider()->sourceType() == SourceProviderSourceType::WebAssembly);757 }758 759 void WebAssemblyExecutable::destroy(JSCell* cell)760 {761 static_cast<WebAssemblyExecutable*>(cell)->WebAssemblyExecutable::~WebAssemblyExecutable();762 }763 764 void WebAssemblyExecutable::visitChildren(JSCell* cell, SlotVisitor& visitor)765 {766 WebAssemblyExecutable* thisObject = jsCast<WebAssemblyExecutable*>(cell);767 ASSERT_GC_OBJECT_INHERITS(thisObject, info());768 ExecutableBase::visitChildren(thisObject, visitor);769 if (thisObject->m_codeBlockForCall)770 thisObject->m_codeBlockForCall->visitWeakly(visitor);771 visitor.append(&thisObject->m_module);772 }773 #endif774 775 void ExecutableBase::dump(PrintStream& out) const776 {777 ExecutableBase* realThis = const_cast<ExecutableBase*>(this);778 779 if (classInfo() == NativeExecutable::info()) {780 NativeExecutable* native = jsCast<NativeExecutable*>(realThis);781 out.print("NativeExecutable:", RawPointer(bitwise_cast<void*>(native->function())), "/", RawPointer(bitwise_cast<void*>(native->constructor())));782 return;783 }784 785 if (classInfo() == EvalExecutable::info()) {786 EvalExecutable* eval = jsCast<EvalExecutable*>(realThis);787 if (CodeBlock* codeBlock = eval->codeBlock())788 out.print(*codeBlock);789 else790 out.print("EvalExecutable w/o CodeBlock");791 return;792 }793 794 if (classInfo() == ProgramExecutable::info()) {795 ProgramExecutable* eval = jsCast<ProgramExecutable*>(realThis);796 if (CodeBlock* codeBlock = eval->codeBlock())797 out.print(*codeBlock);798 else799 out.print("ProgramExecutable w/o CodeBlock");800 return;801 }802 803 if (classInfo() == ModuleProgramExecutable::info()) {804 ModuleProgramExecutable* executable = jsCast<ModuleProgramExecutable*>(realThis);805 if (CodeBlock* codeBlock = executable->codeBlock())806 out.print(*codeBlock);807 else808 out.print("ModuleProgramExecutable w/o CodeBlock");809 return;810 }811 812 FunctionExecutable* function = jsCast<FunctionExecutable*>(realThis);813 if (!function->eitherCodeBlock())814 out.print("FunctionExecutable w/o CodeBlock");815 else {816 CommaPrinter comma("/");817 if (function->codeBlockForCall())818 out.print(comma, *function->codeBlockForCall());819 if (function->codeBlockForConstruct())820 out.print(comma, *function->codeBlockForConstruct());821 }822 }823 824 CodeBlockHash ExecutableBase::hashFor(CodeSpecializationKind kind) const825 {826 if (this->classInfo() == NativeExecutable::info())827 return jsCast<const NativeExecutable*>(this)->hashFor(kind);828 829 return jsCast<const ScriptExecutable*>(this)->hashFor(kind);830 }831 832 78 CodeBlockHash NativeExecutable::hashFor(CodeSpecializationKind kind) const 833 79 { … … 839 85 } 840 86 841 CodeBlockHash ScriptExecutable::hashFor(CodeSpecializationKind kind) const 842 { 843 return CodeBlockHash(source(), kind); 844 } 845 846 } 87 } // namespace JSC
Note:
See TracChangeset
for help on using the changeset viewer.