void FunctionImp::initialCompile(ExecState* newExec) { FunctionBodyNode* body = this->body.get(); // Reserve various slots needed for the activation object. We do it only once, // --- isCompiled() would return true even if debugging state changed body->reserveSlot(ActivationImp::LengthSlot, false); body->reserveSlot(ActivationImp::TearOffNeeded, false); body->reserveSlot(ActivationImp::ScopeLink, false /* will mark via ScopeChain::mark() */); body->reserveSlot(ActivationImp::FunctionSlot, true); body->reserveSlot(ActivationImp::ArgumentsObjectSlot, true); // Create declarations for parameters, and allocate the symbols. // We always just give them sequential positions, to make passInParameters // simple (though perhaps wasting memory in the trivial case) for (size_t i = 0; i < body->numParams(); ++i) body->addSymbolOverwriteID(i + ActivationImp::NumReservedSlots, body->paramName(i), DontDelete); body->processDecls(newExec); body->compile(FunctionCode, newExec->dynamicInterpreter()->debugger() ? Debug : Release); }
// ECMA 10.1.6 void ActivationImp::setup(ExecState* exec, FunctionImp *function, const List* arguments, LocalStorageEntry* entries) { FunctionBodyNode* body = function->body.get(); size_t total = body->numLocalsAndRegisters(); localStorage = entries; lengthSlot() = total; // we can now link ourselves into the scope, which will also fix up our scopeLink(). exec->pushVariableObjectScope(this); const FunctionBodyNode::SymbolInfo* symInfo = body->getLocalInfo(); // Setup our fields this->arguments = arguments; functionSlot() = function; argumentsObjectSlot() = jsUndefined(); symbolTable = &body->symbolTable(); // Set the mark/don't mark flags and attributes for everything for (size_t p = 0; p < total; ++p) entries[p].attributes = symInfo[p].attr; // Pass in the parameters (ECMA 10.1.3q) #ifdef KJS_VERBOSE fprintf(stderr, "%s---------------------------------------------------\n" "%sprocessing parameters for %s call\n", ind(), ind(), function->functionName().isEmpty() ? "(internal)" : function->functionName().ascii()); #endif size_t numParams = body->numParams(); size_t numPassedIn = min(numParams, static_cast<size_t>(arguments->size())); size_t pos = 0; for (; pos < numPassedIn; ++pos) { size_t symNum = pos + ActivationImp::NumReservedSlots; JSValue* v = arguments->atUnchecked(pos); entries[symNum].val.valueVal = v; #ifdef KJS_VERBOSE fprintf(stderr, "%s setting parameter %s", ind(), body->paramName(pos).ascii()); printInfo(exec, "to", v); #endif } for (; pos < numParams; ++pos) { size_t symNum = pos + ActivationImp::NumReservedSlots; entries[symNum].val.valueVal = jsUndefined(); #ifdef KJS_VERBOSE fprintf(stderr, "%s setting parameter %s to undefined (not passed in)", ind(), body->paramName(pos).ascii()); #endif } #ifdef KJS_VERBOSE fprintf(stderr, "\n%s---------------------------------\n", ind()); fprintf(stderr, "%sBody:\n", ind()); fprintf(stderr, "%s---------------------------------\n", ind()); printInd(body->toString().ascii()); fprintf(stderr, "\n%s---------------------------------\n\n", ind()); #endif // Initialize the rest of the locals to 'undefined' for (size_t pos = numParams + ActivationImp::NumReservedSlots; pos < total; ++pos) entries[pos].val.valueVal = jsUndefined(); // Finally, put in the functions. Note that this relies on above // steps to have completed, since it can trigger a GC. size_t numFuns = body->numFunctionLocals(); size_t* funsData = body->getFunctionLocalInfo(); for (size_t fun = 0; fun < numFuns; ++fun) { size_t id = funsData[fun]; entries[id].val.valueVal = symInfo[id].funcDecl->makeFunctionObject(exec); } }