bool gmLibHooks::AddFunction(gmFunctionInfo &a_info) { // write the function into the stream m_functionStream << (gmuint32) ID_func; m_functionStream << (gmuint32) a_info.m_id; m_functionStream << (gmuint32) ((a_info.m_root) ? 1 : 0); m_functionStream << (gmuint32) a_info.m_numParams; m_functionStream << (gmuint32) a_info.m_numLocals; m_functionStream << (gmuint32) a_info.m_maxStackSize; m_functionStream << (gmuint32) a_info.m_byteCodeLength; m_functionStream.Write(a_info.m_byteCode, a_info.m_byteCodeLength); if(m_debug) { int numSymbols = a_info.m_numLocals + a_info.m_numParams, i; // debug name m_functionStream << (gmuint32) GetSymbolId(a_info.m_debugName); // line info m_functionStream << (gmuint32) a_info.m_lineInfoCount; for(i = 0; i < a_info.m_lineInfoCount; ++i) { m_functionStream << (gmuint32) a_info.m_lineInfo[i].m_address; m_functionStream << (gmuint32) a_info.m_lineInfo[i].m_lineNumber; } // symbol info for(i = 0; i < numSymbols; ++i) { if(a_info.m_symbols) { m_functionStream << (gmuint32) GetSymbolId(a_info.m_symbols[i]); } else { m_functionStream << (gmuint32) (~0); } } } return true; }
gmptr gmLibHooks::GetStringId(const char * a_string) { return GetSymbolId(a_string); }
// // Load persisted scope info. // void ScopeInfo::GetScopeInfo(Parser *parser, ByteCodeGenerator* byteCodeGenerator, FuncInfo* funcInfo, Scope* scope) { ScriptContext* scriptContext; ArenaAllocator* alloc; // Load scope attributes and push onto scope stack. scope->SetIsDynamic(this->isDynamic); if (this->isObject) { scope->SetIsObject(); } scope->SetMustInstantiate(this->mustInstantiate); if (!this->GetCanMergeWithBodyScope()) { scope->SetCannotMergeWithBodyScope(); } scope->SetHasOwnLocalInClosure(this->hasLocalInClosure); if (parser) { scriptContext = parser->GetScriptContext(); alloc = parser->GetAllocator(); } else { TRACE_BYTECODE(_u("\nRestore ScopeInfo: %s #symbols: %d %s\n"), funcInfo->name, symbolCount, isObject ? _u("isObject") : _u("")); Assert(!this->isCached || scope == funcInfo->GetBodyScope()); funcInfo->SetHasCachedScope(this->isCached); byteCodeGenerator->PushScope(scope); // The scope is already populated, so we're done. return; } // Load scope symbols // On first access to the scopeinfo, replace the ID's with PropertyRecord*'s to save the dictionary lookup // on later accesses. Replace them all before allocating Symbol's to prevent inconsistency on OOM. if (!this->areNamesCached && !PHASE_OFF1(Js::CacheScopeInfoNamesPhase)) { for (int i = 0; i < symbolCount; i++) { PropertyId propertyId = GetSymbolId(i); if (propertyId != 0) // There may be empty slots, e.g. "arguments" may have no slot { PropertyRecord const* name = scriptContext->GetPropertyName(propertyId); this->SetPropertyName(i, name); } } this->areNamesCached = true; } for (int i = 0; i < symbolCount; i++) { PropertyRecord const* name = nullptr; if (this->areNamesCached) { name = this->GetPropertyName(i); } else { PropertyId propertyId = GetSymbolId(i); if (propertyId != 0) // There may be empty slots, e.g. "arguments" may have no slot { name = scriptContext->GetPropertyName(propertyId); } } if (name != nullptr) { SymbolType symbolType = GetSymbolType(i); SymbolName symName(name->GetBuffer(), name->GetLength()); Symbol *sym = Anew(alloc, Symbol, symName, nullptr, symbolType); sym->SetScopeSlot(static_cast<PropertyId>(i)); sym->SetIsBlockVar(GetIsBlockVariable(i)); if (GetHasFuncAssignment(i)) { sym->RestoreHasFuncAssignment(); } scope->AddNewSymbol(sym); if (parser) { parser->RestorePidRefForSym(sym); } TRACE_BYTECODE(_u("%12s %d\n"), sym->GetName().GetBuffer(), sym->GetScopeSlot()); } } this->scope = scope; DebugOnly(scope->isRestored = true); }