JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType) { SamplingRegion samplingRegion(jitType == JITCode::BaselineJIT ? "Baseline Compilation (TOTAL)" : "DFG Compilation (TOTAL)"); #if !ENABLE(JIT) UNUSED_PARAM(jitType); #endif JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); if (!!m_evalCodeBlock && m_evalCodeBlock->canProduceCopyWithBytecode()) { BytecodeDestructionBlocker blocker(m_evalCodeBlock.get()); OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock)); newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release())); m_evalCodeBlock = newCodeBlock.release(); } else { if (!lexicalGlobalObject->evalEnabled()) return throwError(exec, createEvalError(exec, "Eval is disabled")); RefPtr<EvalNode> evalNode = parse<EvalNode>(globalData, lexicalGlobalObject, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, EvalNode::isFunctionNode ? JSParseFunctionCode : JSParseProgramCode, lexicalGlobalObject->debugger(), exec, &exception); if (!evalNode) { ASSERT(exception); return exception; } recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine()); JSGlobalObject* globalObject = scopeChainNode->globalObject.get(); OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release(); ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock); m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChainNode->localDepth(), previousCodeBlock.release())); OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChainNode, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get(), !!m_evalCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation))); if ((exception = generator->generate())) { m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative()); evalNode->destroyData(); return exception; } evalNode->destroyData(); m_evalCodeBlock->copyPostParseDataFromAlternative(); } #if ENABLE(JIT) if (!jitCompileIfAppropriate(*globalData, m_evalCodeBlock, m_jitCodeForCall, jitType)) return 0; #endif #if ENABLE(JIT) #if ENABLE(INTERPRETER) if (!m_jitCodeForCall) Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock)); else #endif Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock) + m_jitCodeForCall.size()); #else Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock)); #endif return 0; }
JSObject* EvalExecutable::compileInternal(ExecState* exec, JSScope* scope, JITCode::JITType jitType, unsigned bytecodeIndex) { SamplingRegion samplingRegion(samplingDescription(jitType)); #if !ENABLE(JIT) UNUSED_PARAM(jitType); UNUSED_PARAM(bytecodeIndex); #endif JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); if (!!m_evalCodeBlock) { OwnPtr<EvalCodeBlock> newCodeBlock = adoptPtr(new EvalCodeBlock(CodeBlock::CopyParsedBlock, *m_evalCodeBlock)); newCodeBlock->setAlternative(static_pointer_cast<CodeBlock>(m_evalCodeBlock.release())); m_evalCodeBlock = newCodeBlock.release(); } else { UNUSED_PARAM(scope); UNUSED_PARAM(globalData); UNUSED_PARAM(lexicalGlobalObject); if (!lexicalGlobalObject->evalEnabled()) return throwError(exec, createEvalError(exec, lexicalGlobalObject->evalDisabledErrorMessage())); JSObject* exception = 0; UnlinkedEvalCodeBlock* unlinkedEvalCode = lexicalGlobalObject->createEvalCodeBlock(exec, this, &exception); if (!unlinkedEvalCode) return exception; OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release(); ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock); m_unlinkedEvalCodeBlock.set(*globalData, this, unlinkedEvalCode); m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, unlinkedEvalCode, lexicalGlobalObject, source().provider(), scope->localDepth(), previousCodeBlock.release())); m_evalCodeBlock->copyPostParseDataFromAlternative(); } #if ENABLE(JIT) if (!prepareForExecution(exec, m_evalCodeBlock, m_jitCodeForCall, jitType, bytecodeIndex)) return 0; #endif #if ENABLE(JIT) Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock) + m_jitCodeForCall.size()); #else Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock)); #endif return 0; }
EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, ThisTDZMode thisTDZMode, const VariableEnvironment* variablesUnderTDZ) { JSGlobalObject* globalObject = exec->lexicalGlobalObject(); if (!globalObject->evalEnabled()) { exec->vm().throwException(exec, createEvalError(exec, globalObject->evalDisabledErrorMessage())); return 0; } EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext); executable->finishCreation(exec->vm()); UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable, thisTDZMode, variablesUnderTDZ); if (!unlinkedEvalCode) return 0; executable->m_unlinkedEvalCodeBlock.set(exec->vm(), executable, unlinkedEvalCode); return executable; }
JSValue JSInjectedScriptHost::evaluate(ExecState* exec) { JSValue expression = exec->argument(0); if (!expression.isString()) return throwError(exec, createError(exec, "String argument expected.")); JSGlobalObject* globalObject = exec->lexicalGlobalObject(); JSFunction* evalFunction = globalObject->evalFunction(); CallData callData; CallType callType = evalFunction->methodTable()->getCallData(evalFunction, callData); if (callType == CallTypeNone) return jsUndefined(); MarkedArgumentBuffer args; args.append(expression); bool wasEvalEnabled = globalObject->evalEnabled(); globalObject->setEvalEnabled(true); JSValue result = JSC::call(exec, evalFunction, callType, callData, exec->globalThisValue(), args); globalObject->setEvalEnabled(wasEvalEnabled); return result; }
EvalExecutable* EvalExecutable::create(ExecState* exec, const SourceCode& source, bool isInStrictContext, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType, const VariableEnvironment* variablesUnderTDZ) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSGlobalObject* globalObject = exec->lexicalGlobalObject(); if (!globalObject->evalEnabled()) { throwException(exec, scope, createEvalError(exec, globalObject->evalDisabledErrorMessage())); return 0; } EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext, derivedContextType, isArrowFunctionContext, evalContextType); executable->finishCreation(vm); UnlinkedEvalCodeBlock* unlinkedEvalCode = globalObject->createEvalCodeBlock(exec, executable, variablesUnderTDZ); if (!unlinkedEvalCode) return 0; executable->m_unlinkedEvalCodeBlock.set(vm, executable, unlinkedEvalCode); return executable; }
JSObject* EvalExecutable::compileInternal(ExecState* exec, ScopeChainNode* scopeChainNode, JITCode::JITType jitType) { #if !ENABLE(JIT) UNUSED_PARAM(jitType); #endif JSObject* exception = 0; JSGlobalData* globalData = &exec->globalData(); JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); if (!lexicalGlobalObject->evalEnabled()) return throwError(exec, createEvalError(exec, "Eval is disabled")); RefPtr<EvalNode> evalNode = globalData->parser->parse<EvalNode>(lexicalGlobalObject, lexicalGlobalObject->debugger(), exec, m_source, 0, isStrictMode() ? JSParseStrict : JSParseNormal, &exception); if (!evalNode) { ASSERT(exception); return exception; } recordParse(evalNode->features(), evalNode->hasCapturedVariables(), evalNode->lineNo(), evalNode->lastLine()); JSGlobalObject* globalObject = scopeChainNode->globalObject.get(); OwnPtr<CodeBlock> previousCodeBlock = m_evalCodeBlock.release(); ASSERT((jitType == JITCode::bottomTierJIT()) == !previousCodeBlock); m_evalCodeBlock = adoptPtr(new EvalCodeBlock(this, globalObject, source().provider(), scopeChainNode->localDepth(), previousCodeBlock.release())); OwnPtr<BytecodeGenerator> generator(adoptPtr(new BytecodeGenerator(evalNode.get(), scopeChainNode, m_evalCodeBlock->symbolTable(), m_evalCodeBlock.get(), !!m_evalCodeBlock->alternative() ? OptimizingCompilation : FirstCompilation))); if ((exception = generator->generate())) { m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative()); evalNode->destroyData(); return exception; } evalNode->destroyData(); m_evalCodeBlock->copyDataFromAlternative(); #if ENABLE(JIT) if (exec->globalData().canUseJIT()) { bool dfgCompiled = false; if (jitType == JITCode::DFGJIT) dfgCompiled = DFG::tryCompile(exec, m_evalCodeBlock.get(), m_jitCodeForCall); if (dfgCompiled) ASSERT(!m_evalCodeBlock->alternative() || !m_evalCodeBlock->alternative()->hasIncomingCalls()); else { if (m_evalCodeBlock->alternative()) { // There is already an alternative piece of code compiled with a different // JIT, so we can silently fail. m_evalCodeBlock = static_pointer_cast<EvalCodeBlock>(m_evalCodeBlock->releaseAlternative()); return 0; } m_jitCodeForCall = JIT::compile(scopeChainNode->globalData, m_evalCodeBlock.get()); } #if !ENABLE(OPCODE_SAMPLING) if (!BytecodeGenerator::dumpsGeneratedCode()) m_evalCodeBlock->discardBytecode(); #endif m_evalCodeBlock->setJITCode(m_jitCodeForCall, MacroAssemblerCodePtr()); } #endif #if ENABLE(JIT) #if ENABLE(INTERPRETER) if (!m_jitCodeForCall) Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock)); else #endif Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock) + m_jitCodeForCall.size()); #else Heap::heap(this)->reportExtraMemoryCost(sizeof(*m_evalCodeBlock)); #endif return 0; }