Changeset 153221 in webkit for trunk/Source/JavaScriptCore/bytecompiler
- Timestamp:
- Jul 24, 2013, 9:02:40 PM (12 years ago)
- Location:
- trunk/Source/JavaScriptCore/bytecompiler
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r153200 r153221 32 32 #include "BytecodeGenerator.h" 33 33 34 #include "BatchedTransitionOptimizer.h"35 34 #include "Interpreter.h" 36 35 #include "JSActivation.h" … … 56 55 m_generator->m_instructions[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first; 57 56 } 58 59 #ifndef NDEBUG60 void ResolveResult::checkValidity()61 {62 switch (m_type) {63 case Register:64 case ReadOnlyRegister:65 ASSERT(m_local);66 return;67 case Dynamic:68 ASSERT(!m_local);69 return;70 case Lexical:71 case ReadOnlyLexical:72 ASSERT(!m_local);73 return;74 default:75 RELEASE_ASSERT_NOT_REACHED();76 }77 }78 #endif79 57 80 58 ParserError BytecodeGenerator::generate() … … 158 136 } 159 137 160 BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope*,ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)138 BytecodeGenerator::BytecodeGenerator(VM& vm, ProgramNode* programNode, UnlinkedProgramCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) 161 139 : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn) 162 140 , m_shouldEmitProfileHooks(profilerMode == ProfilerOn) … … 168 146 , m_globalObjectRegister(0) 169 147 , m_finallyDepth(0) 170 , m_ dynamicScopeDepth(0)148 , m_localScopeDepth(0) 171 149 , m_codeType(GlobalCode) 172 150 , m_nextConstantOffset(0) … … 206 184 } 207 185 208 BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope,FunctionBodyNode* functionBody, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)186 BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, UnlinkedFunctionCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) 209 187 : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn) 210 188 , m_shouldEmitProfileHooks(profilerMode == ProfilerOn) 211 189 , m_symbolTable(codeBlock->symbolTable()) 212 190 , m_scopeNode(functionBody) 213 , m_scope(vm, scope)214 191 , m_codeBlock(vm, codeBlock) 215 192 , m_activationRegister(0) … … 217 194 , m_globalObjectRegister(0) 218 195 , m_finallyDepth(0) 219 , m_ dynamicScopeDepth(0)196 , m_localScopeDepth(0) 220 197 , m_codeType(FunctionCode) 221 198 , m_nextConstantOffset(0) … … 403 380 } 404 381 405 BytecodeGenerator::BytecodeGenerator(VM& vm, JSScope* scope,EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode)382 BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCodeBlock* codeBlock, DebuggerMode debuggerMode, ProfilerMode profilerMode) 406 383 : m_shouldEmitDebugHooks(debuggerMode == DebuggerOn) 407 384 , m_shouldEmitProfileHooks(profilerMode == ProfilerOn) 408 385 , m_symbolTable(codeBlock->symbolTable()) 409 386 , m_scopeNode(evalNode) 410 , m_scope(vm, scope)411 387 , m_codeBlock(vm, codeBlock) 412 388 , m_thisRegister(CallFrame::thisArgumentOffset()) … … 414 390 , m_globalObjectRegister(0) 415 391 , m_finallyDepth(0) 416 , m_ dynamicScopeDepth(0)392 , m_localScopeDepth(0) 417 393 , m_codeType(EvalCode) 418 394 , m_nextConstantOffset(0) … … 471 447 472 448 // If non-strict eval is in play, we use a separate object in the scope chain for the callee's name. 473 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) { 474 emitOpcode(op_push_name_scope); 475 instructions().append(addConstant(functionBodyNode->ident())); 476 instructions().append(m_calleeRegister.index()); 477 instructions().append(ReadOnly | DontDelete); 478 return 0; 479 } 449 if ((m_codeBlock->usesEval() && !m_codeBlock->isStrictMode()) || m_shouldEmitDebugHooks) 450 emitPushNameScope(functionBodyNode->ident(), &m_calleeRegister, ReadOnly | DontDelete); 480 451 481 452 if (!functionBodyNode->captures(functionBodyNode->ident())) … … 1161 1132 } 1162 1133 1163 ResolveResult BytecodeGenerator::resolve(const Identifier& property)1134 Local BytecodeGenerator::local(const Identifier& property) 1164 1135 { 1165 1136 if (property == propertyNames().thisIdentifier) 1166 return ResolveResult::registerResolve(thisRegister(), ResolveResult::ReadOnlyFlag); 1167 1168 // Check if the property should be allocated in a register. 1169 if (m_codeType != GlobalCode && shouldOptimizeLocals() && m_symbolTable) { 1170 SymbolTableEntry entry = symbolTable().get(property.impl()); 1171 if (!entry.isNull()) { 1172 if (property == propertyNames().arguments) 1173 createArgumentsIfNecessary(); 1174 unsigned flags = entry.isReadOnly() ? ResolveResult::ReadOnlyFlag : 0; 1175 RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); 1176 return ResolveResult::registerResolve(local, flags); 1177 } 1178 } 1179 // Cases where we cannot statically optimize the lookup. 1180 if (property == propertyNames().arguments || !canOptimizeNonLocals()) 1181 return ResolveResult::dynamicResolve(); 1182 1183 if (!m_scope || m_codeType != FunctionCode || m_shouldEmitDebugHooks) 1184 return ResolveResult::dynamicResolve(); 1185 1186 ScopeChainIterator iter = m_scope->begin(); 1187 ScopeChainIterator end = m_scope->end(); 1188 size_t depth = m_codeBlock->needsFullScopeChain(); 1189 unsigned flags = 0; 1190 for (; iter != end; ++iter, ++depth) { 1191 JSObject* currentScope = iter.get(); 1192 if (!currentScope->isStaticScopeObject()) 1193 return ResolveResult::dynamicResolve(); 1194 1195 JSSymbolTableObject* currentVariableObject = jsCast<JSSymbolTableObject*>(currentScope); 1196 SymbolTableEntry entry = currentVariableObject->symbolTable()->get(property.impl()); 1197 1198 // Found the property 1199 if (!entry.isNull()) { 1200 if (entry.isReadOnly()) 1201 flags |= ResolveResult::ReadOnlyFlag; 1202 if (++iter == end) 1203 return ResolveResult::dynamicResolve(); 1204 #if !ASSERT_DISABLED 1205 if (JSActivation* activation = jsDynamicCast<JSActivation*>(currentVariableObject)) 1206 ASSERT(activation->isValid(entry)); 1207 #endif 1208 return ResolveResult::lexicalResolve(entry.getIndex(), depth, flags); 1209 } 1210 bool scopeRequiresDynamicChecks = false; 1211 if (currentVariableObject->isDynamicScope(scopeRequiresDynamicChecks)) 1212 break; 1213 if (scopeRequiresDynamicChecks) 1214 flags |= ResolveResult::DynamicFlag; 1215 } 1216 1217 return ResolveResult::dynamicResolve(); 1218 } 1219 1220 ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property) 1221 { 1222 // Register-allocated const declarations. 1223 if (m_codeType == FunctionCode && m_symbolTable) { 1224 SymbolTableEntry entry = symbolTable().get(property.impl()); 1225 if (!entry.isNull()) { 1226 unsigned flags = entry.isReadOnly() ? ResolveResult::ReadOnlyFlag : 0; 1227 RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); 1228 return ResolveResult::registerResolve(local, flags); 1229 } 1230 } 1231 1232 return ResolveResult::dynamicResolve(); 1137 return Local(thisRegister(), ReadOnly); 1138 1139 if (property == propertyNames().arguments) 1140 createArgumentsIfNecessary(); 1141 1142 if (!shouldOptimizeLocals()) 1143 return Local(); 1144 1145 SymbolTableEntry entry = symbolTable().get(property.impl()); 1146 if (entry.isNull()) 1147 return Local(); 1148 1149 RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); 1150 return Local(local, entry.getAttributes()); 1151 } 1152 1153 Local BytecodeGenerator::constLocal(const Identifier& property) 1154 { 1155 if (m_codeType != FunctionCode) 1156 return Local(); 1157 1158 SymbolTableEntry entry = symbolTable().get(property.impl()); 1159 if (entry.isNull()) 1160 return Local(); 1161 1162 RegisterID* local = createLazyRegisterIfNecessary(®isterFor(entry.getIndex())); 1163 return Local(local, entry.getAttributes()); 1233 1164 } 1234 1165 … … 1241 1172 instructions().append(base->index()); 1242 1173 instructions().append(target->bind(begin, instructions().size())); 1174 } 1175 1176 // Indicates the least upper bound of resolve type based on local scope. The bytecode linker 1177 // will start with this ResolveType and compute the least upper bound including intercepting scopes. 1178 ResolveType BytecodeGenerator::resolveType() 1179 { 1180 if (m_localScopeDepth) 1181 return Dynamic; 1182 if (m_symbolTable && m_symbolTable->usesNonStrictEval()) 1183 return GlobalPropertyWithVarInjectionChecks; 1184 return GlobalProperty; 1185 } 1186 1187 RegisterID* BytecodeGenerator::emitResolveScope(RegisterID* dst, const Identifier& identifier) 1188 { 1189 ASSERT(!m_symbolTable || !m_symbolTable->contains(identifier.impl()) || resolveType() == Dynamic); 1190 1191 // resolve_scope dst, id, ResolveType, depth 1192 emitOpcode(op_resolve_scope); 1193 instructions().append(kill(dst)); 1194 instructions().append(addConstant(identifier)); 1195 instructions().append(resolveType()); 1196 instructions().append(0); 1197 return dst; 1198 } 1199 1200 RegisterID* BytecodeGenerator::emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier& identifier, ResolveMode resolveMode) 1201 { 1202 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1203 1204 // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand 1205 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_scope); 1206 instructions().append(kill(dst)); 1207 instructions().append(scope->index()); 1208 instructions().append(addConstant(identifier)); 1209 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand()); 1210 instructions().append(0); 1211 instructions().append(0); 1212 instructions().append(profile); 1213 return dst; 1214 } 1215 1216 RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode) 1217 { 1218 m_codeBlock->addPropertyAccessInstruction(instructions().size()); 1219 1220 // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand 1221 emitOpcode(op_put_to_scope); 1222 instructions().append(scope->index()); 1223 instructions().append(addConstant(identifier)); 1224 instructions().append(value->index()); 1225 instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand()); 1226 instructions().append(0); 1227 instructions().append(0); 1228 return value; 1243 1229 } 1244 1230 … … 1252 1238 } 1253 1239 1254 bool BytecodeGenerator::shouldAvoidResolveGlobal()1255 {1256 return !m_labelScopes.size();1257 }1258 1259 RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)1260 {1261 1262 if (resolveResult.isStatic())1263 return emitGetStaticVar(dst, resolveResult, property);1264 1265 UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve);1266 instructions().append(kill(dst));1267 instructions().append(addConstant(property));1268 instructions().append(getResolveOperations(property));1269 instructions().append(profile);1270 return dst;1271 }1272 1273 RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)1274 {1275 if (!resolveResult.isDynamic()) {1276 // Global object is the base1277 return emitLoadGlobalObject(dst);1278 }1279 1280 // We can't optimise at all :-(1281 UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve_base);1282 instructions().append(kill(dst));1283 instructions().append(addConstant(property));1284 instructions().append(false);1285 instructions().append(getResolveBaseOperations(property));1286 instructions().append(0);1287 instructions().append(profile);1288 return dst;1289 }1290 1291 RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const ResolveResult&, const Identifier& property, NonlocalResolveInfo& verifier)1292 {1293 // We can't optimise at all :-(1294 UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve_base);1295 instructions().append(kill(dst));1296 instructions().append(addConstant(property));1297 instructions().append(m_codeBlock->isStrictMode());1298 uint32_t putToBaseIndex = 0;1299 instructions().append(getResolveBaseForPutOperations(property, putToBaseIndex));1300 verifier.resolved(putToBaseIndex);1301 instructions().append(putToBaseIndex);1302 instructions().append(profile);1303 return dst;1304 }1305 1306 RegisterID* BytecodeGenerator::emitResolveWithBaseForPut(RegisterID* baseDst, RegisterID* propDst, const ResolveResult& resolveResult, const Identifier& property, NonlocalResolveInfo& verifier)1307 {1308 ASSERT_UNUSED(resolveResult, !resolveResult.isStatic());1309 UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve_with_base);1310 instructions().append(kill(baseDst));1311 instructions().append(propDst->index());1312 instructions().append(addConstant(property));1313 uint32_t putToBaseIndex = 0;1314 instructions().append(getResolveWithBaseForPutOperations(property, putToBaseIndex));1315 verifier.resolved(putToBaseIndex);1316 instructions().append(putToBaseIndex);1317 instructions().append(profile);1318 return baseDst;1319 }1320 1321 RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const ResolveResult& resolveResult, const Identifier& property)1322 {1323 if (resolveResult.isStatic()) {1324 emitLoad(baseDst, jsUndefined());1325 emitGetStaticVar(propDst, resolveResult, property);1326 return baseDst;1327 }1328 1329 UnlinkedValueProfile profile = emitProfiledOpcode(op_resolve_with_this);1330 instructions().append(kill(baseDst));1331 instructions().append(propDst->index());1332 instructions().append(addConstant(property));1333 instructions().append(getResolveWithThisOperations(property));1334 instructions().append(profile);1335 return baseDst;1336 }1337 1338 RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult, const Identifier&)1339 {1340 ASSERT(m_codeType == FunctionCode);1341 switch (resolveResult.type()) {1342 case ResolveResult::Register:1343 case ResolveResult::ReadOnlyRegister:1344 if (dst == ignoredResult())1345 return 0;1346 return moveToDestinationIfNeeded(dst, resolveResult.local());1347 1348 case ResolveResult::Lexical:1349 case ResolveResult::ReadOnlyLexical: {1350 UnlinkedValueProfile profile = emitProfiledOpcode(op_get_scoped_var);1351 instructions().append(dst->index());1352 instructions().append(resolveResult.index());1353 instructions().append(resolveResult.depth());1354 instructions().append(profile);1355 return dst;1356 }1357 1358 default:1359 RELEASE_ASSERT_NOT_REACHED();1360 return 0;1361 }1362 }1363 1364 1240 RegisterID* BytecodeGenerator::emitInitGlobalConst(const Identifier& identifier, RegisterID* value) 1365 1241 { … … 1371 1247 instructions().append(addConstant(identifier)); 1372 1248 return value; 1373 }1374 1375 RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, const Identifier&, RegisterID* value)1376 {1377 ASSERT(m_codeType == FunctionCode);1378 switch (resolveResult.type()) {1379 case ResolveResult::Register:1380 case ResolveResult::ReadOnlyRegister:1381 return moveToDestinationIfNeeded(resolveResult.local(), value);1382 1383 case ResolveResult::Lexical:1384 case ResolveResult::ReadOnlyLexical:1385 emitOpcode(op_put_scoped_var);1386 instructions().append(resolveResult.index());1387 instructions().append(resolveResult.depth());1388 instructions().append(value->index());1389 return value;1390 1391 default:1392 RELEASE_ASSERT_NOT_REACHED();1393 return 0;1394 }1395 1249 } 1396 1250 … … 1438 1292 instructions().append(0); 1439 1293 instructions().append(0); 1440 return value;1441 }1442 1443 RegisterID* BytecodeGenerator::emitPutToBase(RegisterID* base, const Identifier& property, RegisterID* value, NonlocalResolveInfo& resolveInfo)1444 {1445 emitOpcode(op_put_to_base);1446 instructions().append(base->index());1447 instructions().append(addConstant(property));1448 instructions().append(value->index());1449 instructions().append(resolveInfo.put());1450 1294 return value; 1451 1295 } … … 2007 1851 context.isFinallyBlock = false; 2008 1852 m_scopeContextStack.append(context); 2009 m_ dynamicScopeDepth++;1853 m_localScopeDepth++; 2010 1854 2011 1855 return emitUnaryNoDstOp(op_push_with_scope, scope); … … 2020 1864 2021 1865 m_scopeContextStack.removeLast(); 2022 m_ dynamicScopeDepth--;1866 m_localScopeDepth--; 2023 1867 } 2024 1868 … … 2053 1897 static_cast<unsigned>(m_labelScopes.size()), 2054 1898 m_finallyDepth, 2055 m_ dynamicScopeDepth1899 m_localScopeDepth 2056 1900 }; 2057 1901 scope.finallyContext = context; … … 2222 2066 int savedFinallyDepth = m_finallyDepth; 2223 2067 m_finallyDepth = finallyContext.finallyDepth; 2224 int savedDynamicScopeDepth = m_ dynamicScopeDepth;2225 m_ dynamicScopeDepth = finallyContext.dynamicScopeDepth;2068 int savedDynamicScopeDepth = m_localScopeDepth; 2069 m_localScopeDepth = finallyContext.dynamicScopeDepth; 2226 2070 2227 2071 // Emit the finally block. … … 2252 2096 m_labelScopes = savedLabelScopes; 2253 2097 m_finallyDepth = savedFinallyDepth; 2254 m_ dynamicScopeDepth = savedDynamicScopeDepth;2098 m_localScopeDepth = savedDynamicScopeDepth; 2255 2099 2256 2100 --topScope; … … 2335 2179 2336 2180 emitLabel(tryRange.tryData->target.get()); 2337 tryRange.tryData->targetScopeDepth = m_ dynamicScopeDepth;2181 tryRange.tryData->targetScopeDepth = m_localScopeDepth; 2338 2182 2339 2183 emitOpcode(op_catch); … … 2354 2198 context.isFinallyBlock = false; 2355 2199 m_scopeContextStack.append(context); 2356 m_ dynamicScopeDepth++;2200 m_localScopeDepth++; 2357 2201 2358 2202 emitOpcode(op_push_name_scope); … … 2492 2336 bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber) 2493 2337 { 2494 RegisterID* registerID = resolve(ident).local();2338 RegisterID* registerID = local(ident).get(); 2495 2339 if (!registerID || registerID->index() >= 0) 2496 2340 return 0; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r153201 r153221 54 54 class Identifier; 55 55 class Label; 56 class JSScope;57 56 58 57 enum ExpectedFunction { … … 114 113 }; 115 114 115 class Local { 116 public: 117 Local() 118 : m_local(0) 119 , m_attributes(0) 120 { 121 } 122 123 Local(RegisterID* local, unsigned attributes) 124 : m_local(local) 125 , m_attributes(attributes) 126 { 127 } 128 129 operator bool() { return m_local; } 130 131 RegisterID* get() { return m_local; } 132 133 bool isReadOnly() { return m_attributes & ReadOnly; } 134 135 private: 136 RegisterID* m_local; 137 unsigned m_attributes; 138 }; 139 116 140 struct TryRange { 117 141 RefPtr<Label> start; 118 142 RefPtr<Label> end; 119 143 TryData* tryData; 120 };121 122 class ResolveResult {123 public:124 enum Flags {125 // The property is locally bound, in a register.126 RegisterFlag = 0x1,127 // We need to traverse the scope chain at runtime, checking for128 // non-strict eval and/or `with' nodes.129 DynamicFlag = 0x2,130 // The resolved binding is immutable.131 ReadOnlyFlag = 0x4,132 // The property has a static location133 StaticFlag = 0x8,134 // Entry at scope distance "m_depth" and located at "m_index"135 ScopedFlag = 0x10136 };137 138 enum Type {139 // The property is local, and stored in a register.140 Register = RegisterFlag | StaticFlag,141 // A read-only local, created by "const".142 ReadOnlyRegister = RegisterFlag | ReadOnlyFlag | StaticFlag,143 // Lexically fixed location in the scope chain144 Lexical = ScopedFlag | StaticFlag,145 // A read-only Lexical, created by "const".146 ReadOnlyLexical = ScopedFlag | ReadOnlyFlag | StaticFlag,147 // Any other form of lookup148 Dynamic = DynamicFlag,149 };150 151 static ResolveResult registerResolve(RegisterID *local, unsigned flags)152 {153 return ResolveResult(Register | flags, local);154 }155 static ResolveResult dynamicResolve()156 {157 return ResolveResult(Dynamic, 0);158 }159 static ResolveResult lexicalResolve(int index, size_t depth, unsigned flags)160 {161 if (flags & DynamicFlag)162 return dynamicResolve();163 return ResolveResult(Lexical | flags, index, depth);164 }165 unsigned type() const { return m_type; }166 167 // Returns the register corresponding to a local variable, or 0 if no168 // such register exists. Registers returned by ResolveResult::local() do169 // not require explicit reference counting.170 RegisterID* local() const { return m_local; }171 172 bool isRegister() const { return m_type & RegisterFlag; }173 bool isStatic() const { return (m_type & StaticFlag) && !isDynamic(); }174 bool isDynamic() const { return m_type & DynamicFlag; }175 bool isReadOnly() const { return (m_type & ReadOnlyFlag) && !isDynamic(); }176 177 unsigned depth() const { ASSERT(isStatic()); return m_depth; }178 int32_t index() const { ASSERT(isStatic()); return m_index; }179 180 private:181 ResolveResult(unsigned type, RegisterID* local)182 : m_type(type)183 , m_local(local)184 , m_index(0)185 , m_depth(0)186 {187 #ifndef NDEBUG188 checkValidity();189 #endif190 }191 192 ResolveResult(unsigned type, int index, unsigned depth)193 : m_type(type)194 , m_local(0)195 , m_index(index)196 , m_depth(depth)197 {198 #ifndef NDEBUG199 checkValidity();200 #endif201 }202 203 #ifndef NDEBUG204 void checkValidity();205 #endif206 207 unsigned m_type;208 RegisterID* m_local; // Local register, if RegisterFlag is set209 int m_index;210 unsigned m_depth;211 };212 213 struct NonlocalResolveInfo {214 friend class BytecodeGenerator;215 NonlocalResolveInfo()216 : m_state(Unused)217 {218 }219 ~NonlocalResolveInfo()220 {221 ASSERT(m_state == Put);222 }223 private:224 void resolved(uint32_t putToBaseIndex)225 {226 ASSERT(putToBaseIndex);227 ASSERT(m_state == Unused);228 m_state = Resolved;229 m_putToBaseIndex = putToBaseIndex;230 }231 uint32_t put()232 {233 ASSERT(m_state == Resolved);234 m_state = Put;235 return m_putToBaseIndex;236 }237 enum State { Unused, Resolved, Put };238 State m_state;239 uint32_t m_putToBaseIndex;240 144 }; 241 145 … … 246 150 typedef DeclarationStacks::FunctionStack FunctionStack; 247 151 248 BytecodeGenerator(VM&, JSScope*,ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode);249 BytecodeGenerator(VM&, JSScope*,FunctionBodyNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode);250 BytecodeGenerator(VM&, JSScope*,EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode);152 BytecodeGenerator(VM&, ProgramNode*, UnlinkedProgramCodeBlock*, DebuggerMode, ProfilerMode); 153 BytecodeGenerator(VM&, FunctionBodyNode*, UnlinkedFunctionCodeBlock*, DebuggerMode, ProfilerMode); 154 BytecodeGenerator(VM&, EvalNode*, UnlinkedEvalCodeBlock*, DebuggerMode, ProfilerMode); 251 155 252 156 ~BytecodeGenerator(); … … 266 170 RegisterID* uncheckedRegisterForArguments(); 267 171 268 // Resolve an identifier, given the current compile-time scope chain. 269 ResolveResult resolve(const Identifier&); 270 // Behaves as resolve does, but ignores dynamic scope as 271 // dynamic scope should not interfere with const initialisation 272 ResolveResult resolveConstDecl(const Identifier&); 172 Local local(const Identifier&); 173 Local constLocal(const Identifier&); 273 174 274 175 // Returns the register storing "this" … … 436 337 RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); } 437 338 438 RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&, const Identifier&);439 RegisterID* emitPutStaticVar(const ResolveResult&, const Identifier&, RegisterID* value);440 339 RegisterID* emitInitGlobalConst(const Identifier&, RegisterID* value); 441 442 RegisterID* emitResolve(RegisterID* dst, const ResolveResult&, const Identifier& property);443 RegisterID* emitResolveBase(RegisterID* dst, const ResolveResult&, const Identifier& property);444 RegisterID* emitResolveBaseForPut(RegisterID* dst, const ResolveResult&, const Identifier& property, NonlocalResolveInfo&);445 RegisterID* emitResolveWithBaseForPut(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property, NonlocalResolveInfo&);446 RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property);447 448 RegisterID* emitPutToBase(RegisterID* base, const Identifier&, RegisterID* value, NonlocalResolveInfo&);449 340 450 341 RegisterID* emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property); … … 473 364 void emitToPrimitive(RegisterID* dst, RegisterID* src); 474 365 366 ResolveType resolveType(); 367 RegisterID* emitResolveScope(RegisterID* dst, const Identifier&); 368 RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode); 369 RegisterID* emitPutToScope(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode); 370 475 371 PassRefPtr<Label> emitLabel(Label*); 476 372 void emitLoopHint(); … … 507 403 void emitDebugHook(DebugHookID, unsigned firstLine, unsigned lastLine, unsigned charOffset, unsigned lineStart); 508 404 509 int scopeDepth() { return m_ dynamicScopeDepth + m_finallyDepth; }405 int scopeDepth() { return m_localScopeDepth + m_finallyDepth; } 510 406 bool hasFinaliser() { return m_finallyDepth != 0; } 511 407 … … 561 457 typedef HashMap<double, JSValue> NumberMap; 562 458 typedef HashMap<StringImpl*, JSString*, IdentifierRepHash> IdentifierStringMap; 563 typedef struct {564 int resolveOperations;565 int putOperations;566 } ResolveCacheEntry;567 typedef HashMap<StringImpl*, ResolveCacheEntry, IdentifierRepHash> IdentifierResolvePutMap;568 typedef HashMap<StringImpl*, uint32_t, IdentifierRepHash> IdentifierResolveMap;569 459 570 460 // Helper for emitCall() and emitConstruct(). This works because the set of … … 601 491 602 492 void preserveLastVar(); 603 bool shouldAvoidResolveGlobal();604 493 605 494 RegisterID& registerFor(int index) … … 638 527 bool shouldOptimizeLocals() 639 528 { 640 if (m_dynamicScopeDepth)641 return false;642 643 529 if (m_codeType != FunctionCode) 644 530 return false; 645 531 532 if (m_localScopeDepth) 533 return false; 534 646 535 return true; 647 536 } … … 649 538 bool canOptimizeNonLocals() 650 539 { 651 if (m_ dynamicScopeDepth)540 if (m_localScopeDepth) 652 541 return false; 653 542 … … 675 564 676 565 ScopeNode* m_scopeNode; 677 Strong<JSScope> m_scope;678 566 Strong<UnlinkedCodeBlock> m_codeBlock; 679 567 … … 694 582 RefPtr<RegisterID> m_lastVar; 695 583 int m_finallyDepth; 696 int m_ dynamicScopeDepth;584 int m_localScopeDepth; 697 585 CodeType m_codeType; 698 586 … … 724 612 IdentifierStringMap m_stringMap; 725 613 726 uint32_t getResolveOperations(const Identifier& property)727 {728 if (m_dynamicScopeDepth)729 return m_codeBlock->addResolve();730 IdentifierResolveMap::AddResult result = m_resolveCacheMap.add(property.impl(), 0);731 if (result.isNewEntry)732 result.iterator->value = m_codeBlock->addResolve();733 return result.iterator->value;734 }735 736 uint32_t getResolveWithThisOperations(const Identifier& property)737 {738 if (m_dynamicScopeDepth)739 return m_codeBlock->addResolve();740 IdentifierResolveMap::AddResult result = m_resolveWithThisCacheMap.add(property.impl(), 0);741 if (result.isNewEntry)742 result.iterator->value = m_codeBlock->addResolve();743 return result.iterator->value;744 }745 746 uint32_t getResolveBaseOperations(IdentifierResolvePutMap& map, const Identifier& property, uint32_t& putToBaseOperation)747 {748 if (m_dynamicScopeDepth) {749 putToBaseOperation = m_codeBlock->addPutToBase();750 return m_codeBlock->addResolve();751 }752 ResolveCacheEntry entry = {-1, -1};753 IdentifierResolvePutMap::AddResult result = map.add(property.impl(), entry);754 if (result.isNewEntry)755 result.iterator->value.resolveOperations = m_codeBlock->addResolve();756 if (result.iterator->value.putOperations == -1)757 result.iterator->value.putOperations = getPutToBaseOperation(property);758 putToBaseOperation = result.iterator->value.putOperations;759 return result.iterator->value.resolveOperations;760 }761 762 uint32_t getResolveBaseOperations(const Identifier& property)763 {764 uint32_t scratch;765 return getResolveBaseOperations(m_resolveBaseMap, property, scratch);766 }767 768 uint32_t getResolveBaseForPutOperations(const Identifier& property, uint32_t& putToBaseOperation)769 {770 return getResolveBaseOperations(m_resolveBaseForPutMap, property, putToBaseOperation);771 }772 773 uint32_t getResolveWithBaseForPutOperations(const Identifier& property, uint32_t& putToBaseOperation)774 {775 return getResolveBaseOperations(m_resolveWithBaseForPutMap, property, putToBaseOperation);776 }777 778 uint32_t getPutToBaseOperation(const Identifier& property)779 {780 if (m_dynamicScopeDepth)781 return m_codeBlock->addPutToBase();782 IdentifierResolveMap::AddResult result = m_putToBaseMap.add(property.impl(), 0);783 if (result.isNewEntry)784 result.iterator->value = m_codeBlock->addPutToBase();785 return result.iterator->value;786 }787 788 IdentifierResolveMap m_putToBaseMap;789 IdentifierResolveMap m_resolveCacheMap;790 IdentifierResolveMap m_resolveWithThisCacheMap;791 IdentifierResolvePutMap m_resolveBaseMap;792 IdentifierResolvePutMap m_resolveBaseForPutMap;793 IdentifierResolvePutMap m_resolveWithBaseForPutMap;794 795 614 StaticPropertyAnalyzer m_staticPropertyAnalyzer; 796 615 -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r153200 r153221 142 142 bool ResolveNode::isPure(BytecodeGenerator& generator) const 143 143 { 144 return generator. resolve(m_ident).isStatic();144 return generator.local(m_ident).get(); 145 145 } 146 146 147 147 RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 148 148 { 149 ResolveResult resolveResult = generator.resolve(m_ident); 150 if (RegisterID* local = resolveResult.local()) { 149 if (Local local = generator.local(m_ident)) { 151 150 if (dst == generator.ignoredResult()) 152 151 return 0; 153 return generator.moveToDestinationIfNeeded(dst, local );152 return generator.moveToDestinationIfNeeded(dst, local.get()); 154 153 } 155 154 156 155 unsigned divot = m_startOffset + m_ident.length(); 157 156 generator.emitExpressionInfo(divot, m_ident.length(), 0, m_divotLine, m_divotLineStart); 158 return generator.emitResolve(generator.finalDestination(dst), resolveResult, m_ident); 157 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident); 158 return generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound); 159 159 } 160 160 … … 409 409 RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 410 410 { 411 RefPtr<RegisterID> func = generator.tempDestination(dst); 411 if (Local local = generator.local(generator.propertyNames().eval)) { 412 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get()); 413 CallArguments callArguments(generator, m_args); 414 generator.emitLoad(callArguments.thisRegister(), jsUndefined()); 415 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), divotEndOffset(), divotLine(), divotLineStart()); 416 } 417 418 RefPtr<RegisterID> func = generator.newTemporary(); 412 419 CallArguments callArguments(generator, m_args); 413 420 generator.emitExpressionInfo(divot() - divotStartOffset() + 4, 4, 0, divotLine(), divotLineStart()); 414 generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.resolve(generator.propertyNames().eval), generator.propertyNames().eval); 415 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 421 generator.emitResolveScope(callArguments.thisRegister(), generator.propertyNames().eval); 422 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), generator.propertyNames().eval, ThrowIfNotFound); 423 return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), divotEndOffset(), divotLine(), divotLineStart()); 416 424 } 417 425 … … 432 440 { 433 441 ExpectedFunction expectedFunction = generator.expectedFunctionForIdentifier(m_ident); 434 ResolveResult resolveResult = generator.resolve(m_ident); 435 436 if (RegisterID* local = resolveResult.local()) { 437 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local); 442 443 if (Local local = generator.local(m_ident)) { 444 RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local.get()); 438 445 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get()); 439 446 CallArguments callArguments(generator, m_args); … … 444 451 } 445 452 446 if (resolveResult.isStatic()) {447 RefPtr<RegisterID> func = generator.newTemporary();448 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get());449 CallArguments callArguments(generator, m_args);450 generator.emitGetStaticVar(func.get(), resolveResult, m_ident);451 generator.emitLoad(callArguments.thisRegister(), jsUndefined());452 return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart());453 }454 455 453 RefPtr<RegisterID> func = generator.newTemporary(); 456 454 RefPtr<RegisterID> returnValue = generator.finalDestination(dst, func.get()); … … 459 457 460 458 generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0, divotLine(), divotLineStart()); 461 generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), resolveResult, m_ident); 459 generator.emitResolveScope(callArguments.thisRegister(), m_ident); 460 generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound); 462 461 return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 463 462 } … … 633 632 const Identifier& ident = resolve->identifier(); 634 633 635 ResolveResult resolveResult = generator.resolve(ident); 636 637 if (RefPtr<RegisterID> local = resolveResult.local()) { 638 if (resolveResult.isReadOnly()) { 634 if (Local local = generator.local(ident)) { 635 if (local.isReadOnly()) { 639 636 generator.emitReadOnlyExceptionIfNeeded(); 640 local = generator.emitMove(generator.tempDestination(dst), local.get());637 local = Local(generator.emitMove(generator.tempDestination(dst), local.get()), 0); 641 638 } 642 639 return emitPostIncOrDec(generator, generator.finalDestination(dst), local.get(), m_operator); 643 640 } 644 641 645 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {646 RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult, ident);647 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);648 generator.emitPutStaticVar(resolveResult, ident, value.get());649 return oldValue.get();650 }651 652 642 generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 653 RefPtr<RegisterID> value = generator.newTemporary(); 654 NonlocalResolveInfo resolveInfo; 655 RefPtr<RegisterID> base = generator.emitResolveWithBaseForPut(generator.newTemporary(), value.get(), resolveResult, ident, resolveInfo); 643 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), ident); 644 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound); 656 645 RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); 657 generator.emitPutTo Base(base.get(), ident, value.get(), resolveInfo);646 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound); 658 647 return oldValue.get(); 659 648 } … … 720 709 RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 721 710 { 722 ResolveResult resolveResult = generator.resolve(m_ident); 723 if (resolveResult.isRegister()) 711 if (generator.local(m_ident).get()) 724 712 return generator.emitLoad(generator.finalDestination(dst), false); 725 713 726 714 generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 727 Re gisterID* base = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident);728 return generator.emitDeleteById(generator.finalDestination(dst, base ), base, m_ident);715 RefPtr<RegisterID> base = generator.emitResolveScope(generator.tempDestination(dst), m_ident); 716 return generator.emitDeleteById(generator.finalDestination(dst, base.get()), base.get(), m_ident); 729 717 } 730 718 … … 776 764 RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 777 765 { 778 ResolveResult resolveResult = generator.resolve(m_ident); 779 if (RegisterID* local = resolveResult.local()) { 766 if (Local local = generator.local(m_ident)) { 780 767 if (dst == generator.ignoredResult()) 781 768 return 0; 782 return generator.emitTypeOf(generator.finalDestination(dst), local); 783 } 784 785 if (resolveResult.isStatic()) { 786 RefPtr<RegisterID> scratch = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, m_ident); 787 return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get()); 788 } 789 790 RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident); 791 generator.emitGetById(scratch.get(), scratch.get(), m_ident); 769 return generator.emitTypeOf(generator.finalDestination(dst), local.get()); 770 } 771 772 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident); 773 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, DoNotThrowIfNotFound); 792 774 if (dst == generator.ignoredResult()) 793 775 return 0; 794 return generator.emitTypeOf(generator.finalDestination(dst, sc ratch.get()), scratch.get());776 return generator.emitTypeOf(generator.finalDestination(dst, scope.get()), value.get()); 795 777 } 796 778 … … 815 797 const Identifier& ident = resolve->identifier(); 816 798 817 ResolveResult resolveResult = generator.resolve(ident); 818 if (RefPtr<RegisterID> local = resolveResult.local()) { 819 if (resolveResult.isReadOnly()) { 799 if (Local local = generator.local(ident)) { 800 if (local.isReadOnly()) { 820 801 generator.emitReadOnlyExceptionIfNeeded(); 821 local = generator.emitMove(generator.tempDestination(dst), local.get());802 local = Local(generator.emitMove(generator.tempDestination(dst), local.get()), 0); 822 803 } 823 804 emitIncOrDec(generator, local.get(), m_operator); … … 825 806 } 826 807 827 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {828 RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, ident);829 emitIncOrDec(generator, propDst.get(), m_operator);830 generator.emitPutStaticVar(resolveResult, ident, propDst.get());831 return generator.moveToDestinationIfNeeded(dst, propDst.get());832 }833 834 808 generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 835 RefPtr<RegisterID> propDst = generator.tempDestination(dst); 836 NonlocalResolveInfo resolveVerifier; 837 RefPtr<RegisterID> base = generator.emitResolveWithBaseForPut(generator.newTemporary(), propDst.get(), resolveResult, ident, resolveVerifier); 838 emitIncOrDec(generator, propDst.get(), m_operator); 839 generator.emitPutToBase(base.get(), ident, propDst.get(), resolveVerifier); 840 return generator.moveToDestinationIfNeeded(dst, propDst.get()); 809 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), ident); 810 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound); 811 emitIncOrDec(generator, value.get(), m_operator); 812 generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound); 813 return generator.moveToDestinationIfNeeded(dst, value.get()); 841 814 } 842 815 … … 1310 1283 RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1311 1284 { 1312 ResolveResult resolveResult = generator.resolve(m_ident); 1313 1314 if (RegisterID *local = resolveResult.local()) { 1315 if (resolveResult.isReadOnly()) { 1285 if (Local local = generator.local(m_ident)) { 1286 if (local.isReadOnly()) { 1316 1287 generator.emitReadOnlyExceptionIfNeeded(); 1317 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local , m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));1288 return emitReadModifyAssignment(generator, generator.finalDestination(dst), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1318 1289 } 1319 1290 1320 1291 if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { 1321 1292 RefPtr<RegisterID> result = generator.newTemporary(); 1322 generator.emitMove(result.get(), local );1293 generator.emitMove(result.get(), local.get()); 1323 1294 emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1324 generator.emitMove(local , result.get());1295 generator.emitMove(local.get(), result.get()); 1325 1296 return generator.moveToDestinationIfNeeded(dst, result.get()); 1326 1297 } 1327 1298 1328 RegisterID* result = emitReadModifyAssignment(generator, local , local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));1299 RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); 1329 1300 return generator.moveToDestinationIfNeeded(dst, result); 1330 1301 } 1331 1302 1332 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {1333 RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult, m_ident);1334 RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));1335 generator.emitPutStaticVar(resolveResult, m_ident, result);1336 return result;1337 }1338 1339 RefPtr<RegisterID> src1 = generator.tempDestination(dst);1340 1303 generator.emitExpressionInfo(divot() - divotStartOffset() + m_ident.length(), m_ident.length(), 0, divotLine(), divotLineStart()); 1341 NonlocalResolveInfo resolveVerifier;1342 RefPtr<RegisterID> base = generator.emitResolveWithBaseForPut(generator.newTemporary(), src1.get(), resolveResult, m_ident, resolveVerifier);1343 Re gisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);1344 return generator.emitPutTo Base(base.get(), m_ident, result, resolveVerifier);1304 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident); 1305 RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound); 1306 RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); 1307 return generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound); 1345 1308 } 1346 1309 … … 1349 1312 RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) 1350 1313 { 1351 ResolveResult resolveResult = generator.resolve(m_ident); 1352 1353 if (RegisterID* local = resolveResult.local()) { 1354 if (resolveResult.isReadOnly()) { 1314 if (Local local = generator.local(m_ident)) { 1315 if (local.isReadOnly()) { 1355 1316 generator.emitReadOnlyExceptionIfNeeded(); 1356 1317 return generator.emitNode(dst, m_right); 1357 1318 } 1358 RegisterID* result = generator.emitNode(local , m_right);1319 RegisterID* result = generator.emitNode(local.get(), m_right); 1359 1320 return generator.moveToDestinationIfNeeded(dst, result); 1360 1321 } 1361 1322 1362 if (resolveResult.isStatic() && !resolveResult.isReadOnly()) { 1363 if (dst == generator.ignoredResult()) 1364 dst = 0; 1365 RegisterID* value = generator.emitNode(dst, m_right); 1366 generator.emitPutStaticVar(resolveResult, m_ident, value); 1367 return value; 1368 } 1369 1370 NonlocalResolveInfo resolveVerifier; 1371 if (generator.isStrictMode()) 1372 generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 1373 RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, m_ident, resolveVerifier); 1323 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident); 1374 1324 if (dst == generator.ignoredResult()) 1375 1325 dst = 0; 1376 Re gisterID* value= generator.emitNode(dst, m_right);1326 RefPtr<RegisterID> result = generator.emitNode(dst, m_right); 1377 1327 generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 1378 return generator.emitPutTo Base(base.get(), m_ident, value, resolveVerifier);1328 return generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1379 1329 } 1380 1330 … … 1459 1409 RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) 1460 1410 { 1461 ResolveResult resolveResult = generator.resolveConstDecl(m_ident);1462 1463 1411 // FIXME: This code does not match the behavior of const in Firefox. 1464 if (RegisterID* local = resolveResult.local()) {1412 if (RegisterID* local = generator.constLocal(m_ident).get()) { 1465 1413 if (!m_init) 1466 1414 return local; … … 1478 1426 1479 1427 // FIXME: This will result in incorrect assignment if m_ident exists in an intervening with scope. 1480 RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), resolveResult, m_ident);1481 return generator.emitPut ById(base.get(), m_ident, value.get());1428 RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident); 1429 return generator.emitPutToScope(scope.get(), m_ident, value.get(), DoNotThrowIfNotFound); 1482 1430 } 1483 1431 … … 1743 1691 if (m_lexpr->isResolveNode()) { 1744 1692 const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); 1745 ResolveResult resolveResult = generator.resolve(ident);1746 propertyName = resolveResult.local();1693 Local local = generator.local(ident); 1694 propertyName = local.get(); 1747 1695 if (!propertyName) { 1748 1696 propertyName = generator.newTemporary(); 1749 1697 RefPtr<RegisterID> protect = propertyName; 1750 NonlocalResolveInfo resolveVerifier; 1751 if (generator.isStrictMode()) 1752 generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 1753 RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, ident, resolveVerifier); 1754 1698 RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident); 1755 1699 generator.emitExpressionInfo(divot(), divotStartOffset(), divotEndOffset(), divotLine(), divotLineStart()); 1756 generator.emitPutTo Base(base, ident, propertyName, resolveVerifier);1700 generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound); 1757 1701 } else { 1758 1702 expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
Note:
See TracChangeset
for help on using the changeset viewer.