Changeset 106478 in webkit


Ignore:
Timestamp:
Feb 1, 2012, 11:37:00 AM (14 years ago)
Author:
commit-queue@webkit.org
Message:

Refactor identifier resolution in BytecodeGenerator
https://bugs.webkit.org/show_bug.cgi?id=76285

Patch by Andy Wingo <wingo@igalia.com> on 2012-02-01
Reviewed by Geoffrey Garen.

  • bytecompiler/BytecodeGenerator.h:

(JSC::ResolveResult): New class, to describe the storage
location corresponding to an identifier in a program.

  • bytecompiler/BytecodeGenerator.cpp:

(JSC::BytecodeGenerator::resolve): New function, replacing
findScopedProperty.
(JSC::BytecodeGenerator::resolveConstDecl): New function,
encapsulating what ConstDeclNode::emitBytecode used to do.
(JSC::BytecodeGenerator::emitGetStaticVar):
(JSC::BytecodeGenerator::emitPutStaticVar): New functions,
corresponding to the old emitGetScopedVar and emitPutScopedVar.
(JSC::BytecodeGenerator::registerFor): Remove version that took an
Identifier&; replaced by ResolveResult::local().
(JSC::BytecodeGenerator::emitResolve):
(JSC::BytecodeGenerator::emitResolveBase):
(JSC::BytecodeGenerator::emitResolveBaseForPut):
(JSC::BytecodeGenerator::emitResolveWithBase):
(JSC::BytecodeGenerator::emitResolveWithThis): Change to accept a
"resolveResult" argument. This is more clear, and reduces the
amount of double analysis happening at compile-time.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ResolveNode::emitBytecode):
(JSC::EvalFunctionCallNode::emitBytecode):
(JSC::FunctionCallResolveNode::emitBytecode):
(JSC::PostfixResolveNode::emitBytecode):
(JSC::DeleteResolveNode::emitBytecode):
(JSC::TypeOfResolveNode::emitBytecode):
(JSC::PrefixResolveNode::emitBytecode):
(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::AssignResolveNode::emitBytecode):
(JSC::ConstDeclNode::emitCodeSingle):
(JSC::ForInNode::emitBytecode): Refactor to use the new
ResolveResult structure.

Location:
trunk/Source/JavaScriptCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r106454 r106478  
     12012-02-01  Andy Wingo  <wingo@igalia.com>
     2
     3        Refactor identifier resolution in BytecodeGenerator
     4        https://bugs.webkit.org/show_bug.cgi?id=76285
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * bytecompiler/BytecodeGenerator.h:
     9        (JSC::ResolveResult): New class, to describe the storage
     10        location corresponding to an identifier in a program.
     11        * bytecompiler/BytecodeGenerator.cpp:
     12        (JSC::BytecodeGenerator::resolve): New function, replacing
     13        findScopedProperty.
     14        (JSC::BytecodeGenerator::resolveConstDecl): New function,
     15        encapsulating what ConstDeclNode::emitBytecode used to do.
     16        (JSC::BytecodeGenerator::emitGetStaticVar):
     17        (JSC::BytecodeGenerator::emitPutStaticVar): New functions,
     18        corresponding to the old emitGetScopedVar and emitPutScopedVar.
     19        (JSC::BytecodeGenerator::registerFor): Remove version that took an
     20        Identifier&; replaced by ResolveResult::local().
     21        (JSC::BytecodeGenerator::emitResolve):
     22        (JSC::BytecodeGenerator::emitResolveBase):
     23        (JSC::BytecodeGenerator::emitResolveBaseForPut):
     24        (JSC::BytecodeGenerator::emitResolveWithBase):
     25        (JSC::BytecodeGenerator::emitResolveWithThis): Change to accept a
     26        "resolveResult" argument.  This is more clear, and reduces the
     27        amount of double analysis happening at compile-time.
     28        * bytecompiler/NodesCodegen.cpp:
     29        (JSC::ResolveNode::emitBytecode):
     30        (JSC::EvalFunctionCallNode::emitBytecode):
     31        (JSC::FunctionCallResolveNode::emitBytecode):
     32        (JSC::PostfixResolveNode::emitBytecode):
     33        (JSC::DeleteResolveNode::emitBytecode):
     34        (JSC::TypeOfResolveNode::emitBytecode):
     35        (JSC::PrefixResolveNode::emitBytecode):
     36        (JSC::ReadModifyResolveNode::emitBytecode):
     37        (JSC::AssignResolveNode::emitBytecode):
     38        (JSC::ConstDeclNode::emitCodeSingle):
     39        (JSC::ForInNode::emitBytecode): Refactor to use the new
     40        ResolveResult structure.
     41
    1422012-02-01  Csaba Osztrogonác  <ossy@webkit.org>
    243
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r106314 r106478  
    22 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
     4 * Copyright (C) 2012 Igalia, S.L.
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    116117    expected by the callee.
    117118*/
     119
     120#ifndef NDEBUG
     121void ResolveResult::checkValidity()
     122{
     123    switch (m_type) {
     124    case Register:
     125    case ReadOnlyRegister:
     126        ASSERT(m_local);
     127        return;
     128    case Lexical:
     129    case ReadOnlyLexical:
     130    case DynamicLexical:
     131    case DynamicReadOnlyLexical:
     132        ASSERT(m_index != missingSymbolMarker());
     133        return;
     134    case Global:
     135    case DynamicGlobal:
     136        ASSERT(m_globalObject);
     137        return;
     138    case IndexedGlobal:
     139    case ReadOnlyIndexedGlobal:
     140    case DynamicIndexedGlobal:
     141    case DynamicReadOnlyIndexedGlobal:
     142        ASSERT(m_index != missingSymbolMarker());
     143        ASSERT(m_globalObject);
     144        return;
     145    case Dynamic:
     146        return;
     147    default:
     148        ASSERT_NOT_REACHED();
     149    }
     150}
     151#endif
    118152
    119153#ifndef NDEBUG
     
    502536    // each parameter, even if the parameter doesn't make it into the symbol table.
    503537    m_codeBlock->addParameter();
    504 }
    505 
    506 RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
    507 {
    508     if (ident == propertyNames().thisIdentifier)
    509         return &m_thisRegister;
    510        
    511     if (m_codeType == GlobalCode)
    512         return 0;
    513 
    514     if (!shouldOptimizeLocals())
    515         return 0;
    516 
    517     SymbolTableEntry entry = symbolTable().get(ident.impl());
    518     if (entry.isNull())
    519         return 0;
    520 
    521     if (ident == propertyNames().arguments)
    522         createArgumentsIfNecessary();
    523 
    524     return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
    525 }
    526 
    527 RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
    528 {
    529     if (m_codeType == EvalCode)
    530         return 0;
    531 
    532     if (m_codeType == GlobalCode)
    533         return 0;
    534 
    535     SymbolTableEntry entry = symbolTable().get(ident.impl());
    536     if (entry.isNull())
    537         return 0;
    538 
    539     return createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
    540538}
    541539
     
    11711169}
    11721170
    1173 bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, bool& requiresDynamicChecks, JSObject*& globalObject)
    1174 {
     1171ResolveResult BytecodeGenerator::resolve(const Identifier& property)
     1172{
     1173    if (property == propertyNames().thisIdentifier)
     1174        return ResolveResult::registerResolve(thisRegister(), ResolveResult::ReadOnlyFlag);
     1175
     1176    // Check if the property should be allocated in a register.
     1177    if (m_codeType != GlobalCode && shouldOptimizeLocals()) {
     1178        SymbolTableEntry entry = symbolTable().get(property.impl());
     1179        if (!entry.isNull()) {
     1180            if (property == propertyNames().arguments)
     1181                createArgumentsIfNecessary();
     1182            unsigned flags = entry.isReadOnly() ? ResolveResult::ReadOnlyFlag : 0;
     1183            RegisterID* local = createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
     1184            return ResolveResult::registerResolve(local, flags);
     1185        }
     1186    }
     1187
    11751188    // Cases where we cannot statically optimize the lookup.
    11761189    if (property == propertyNames().arguments || !canOptimizeNonLocals()) {
    1177         stackDepth = 0;
    1178         index = missingSymbolMarker();
    1179 
    11801190        if (shouldOptimizeLocals() && m_codeType == GlobalCode) {
    11811191            ScopeChainIterator iter = m_scopeChain->begin();
    1182             globalObject = iter->get();
     1192            JSObject* globalObject = iter->get();
    11831193            ASSERT((++iter) == m_scopeChain->end());
    1184         }
    1185         return false;
    1186     }
    1187 
    1188     size_t depth = 0;
    1189     requiresDynamicChecks = false;
     1194            return ResolveResult::globalResolve(globalObject);
     1195        } else
     1196            return ResolveResult::dynamicResolve(0);
     1197    }
     1198
    11901199    ScopeChainIterator iter = m_scopeChain->begin();
    11911200    ScopeChainIterator end = m_scopeChain->end();
     1201    size_t depth = 0;
     1202    unsigned flags = 0;
     1203    for (; iter != end; ++iter, ++depth) {
     1204        JSObject* currentScope = iter->get();
     1205        if (!currentScope->isVariableObject()) {
     1206            flags |= ResolveResult::DynamicFlag;
     1207            break;
     1208        }       
     1209        JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
     1210        SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
     1211
     1212        // Found the property
     1213        if (!entry.isNull()) {
     1214            if (entry.isReadOnly())
     1215                flags |= ResolveResult::ReadOnlyFlag;
     1216            depth += m_codeBlock->needsFullScopeChain();
     1217            if (++iter == end) {
     1218                if (flags & ResolveResult::DynamicFlag)
     1219                    return ResolveResult::dynamicIndexedGlobalResolve(entry.getIndex(), depth, currentScope, flags);
     1220                return ResolveResult::indexedGlobalResolve(entry.getIndex(), currentScope, flags);
     1221            }
     1222            return ResolveResult::lexicalResolve(entry.getIndex(), depth, flags);
     1223        }
     1224        bool scopeRequiresDynamicChecks = false;
     1225        if (currentVariableObject->isDynamicScope(scopeRequiresDynamicChecks))
     1226            break;
     1227        if (scopeRequiresDynamicChecks)
     1228            flags |= ResolveResult::DynamicFlag;
     1229    }
     1230
     1231    // Can't locate the property but we're able to avoid a few lookups.
     1232    JSObject* scope = iter->get();
     1233    depth += m_codeBlock->needsFullScopeChain();
     1234    if (++iter == end) {
     1235        if ((flags & ResolveResult::DynamicFlag) && depth)
     1236            return ResolveResult::dynamicGlobalResolve(depth, scope);
     1237        return ResolveResult::globalResolve(scope);
     1238    }
     1239    return ResolveResult::dynamicResolve(depth);
     1240}
     1241
     1242ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property)
     1243{
     1244    // Register-allocated const declarations.
     1245    if (m_codeType != EvalCode && m_codeType != GlobalCode) {
     1246        SymbolTableEntry entry = symbolTable().get(property.impl());
     1247        if (!entry.isNull()) {
     1248            unsigned flags = entry.isReadOnly() ? ResolveResult::ReadOnlyFlag : 0;
     1249            RegisterID* local = createLazyRegisterIfNecessary(&registerFor(entry.getIndex()));
     1250            return ResolveResult::registerResolve(local, flags);
     1251        }
     1252    }
     1253
     1254    // Const declarations in eval code or global code.
     1255    ScopeChainIterator iter = scopeChain()->begin();
     1256    ScopeChainIterator end = scopeChain()->end();
     1257    size_t depth = 0;
    11921258    for (; iter != end; ++iter, ++depth) {
    11931259        JSObject* currentScope = iter->get();
    11941260        if (!currentScope->isVariableObject())
    1195             break;
     1261            continue;
    11961262        JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
    11971263        SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl());
    1198 
    1199         // Found the property
    1200         if (!entry.isNull()) {
    1201             if (entry.isReadOnly() && forWriting) {
    1202                 stackDepth = 0;
    1203                 index = missingSymbolMarker();
    1204                 if (++iter == end)
    1205                     globalObject = currentVariableObject;
    1206                 return false;
    1207             }
    1208             stackDepth = depth + m_codeBlock->needsFullScopeChain();
    1209             index = entry.getIndex();
    1210             if (++iter == end)
    1211                 globalObject = currentVariableObject;
    1212             return true;
    1213         }
    1214         bool scopeRequiresDynamicChecks = false;
    1215         if (currentVariableObject->isDynamicScope(scopeRequiresDynamicChecks))
    1216             break;
    1217         requiresDynamicChecks |= scopeRequiresDynamicChecks;
    1218     }
    1219     // Can't locate the property but we're able to avoid a few lookups.
    1220     stackDepth = depth + m_codeBlock->needsFullScopeChain();
    1221     index = missingSymbolMarker();
    1222     JSObject* scope = iter->get();
    1223     if (++iter == end)
    1224         globalObject = scope;
    1225     return true;
     1264        if (entry.isNull())
     1265            continue;
     1266        if (++iter == end)
     1267            return ResolveResult::indexedGlobalResolve(entry.getIndex(), currentVariableObject, 0);
     1268        return ResolveResult::lexicalResolve(entry.getIndex(), depth + scopeDepth(), 0);
     1269    }
     1270
     1271    // FIXME: While this code should only be hit in an eval block, it will assign
     1272    // to the wrong base if property exists in an intervening with scope.
     1273    return ResolveResult::dynamicResolve(scopeDepth());
    12261274}
    12271275
     
    12491297}
    12501298
    1251 RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& property)
    1252 {
    1253     size_t depth = 0;
    1254     int index = 0;
    1255     JSObject* globalObject = 0;
    1256     bool requiresDynamicChecks = false;
    1257     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) && !globalObject) {
    1258         // We can't optimise at all :-(
    1259         ValueProfile* profile = emitProfiledOpcode(op_resolve);
    1260         instructions().append(dst->index());
    1261         instructions().append(addConstant(property));
    1262         instructions().append(profile);
    1263         return dst;
    1264     }
    1265     if (shouldAvoidResolveGlobal()) {
    1266         globalObject = 0;
    1267         requiresDynamicChecks = true;
    1268     }
    1269        
    1270     if (globalObject) {
    1271         if (index != missingSymbolMarker() && !requiresDynamicChecks) {
    1272             // Directly index the property lookup across multiple scopes.
    1273             return emitGetScopedVar(dst, depth, index, globalObject);
    1274         }
    1275 
     1299RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)
     1300{
     1301    if (resolveResult.isStatic())
     1302        return emitGetStaticVar(dst, resolveResult);
     1303   
     1304    if (resolveResult.isGlobal() && !shouldAvoidResolveGlobal()) {
    12761305#if ENABLE(JIT)
    12771306        m_codeBlock->addGlobalResolveInfo(instructions().size());
     
    12801309        m_codeBlock->addGlobalResolveInstruction(instructions().size());
    12811310#endif
    1282         ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
     1311        bool dynamic = resolveResult.isDynamic() && resolveResult.depth();
     1312        ValueProfile* profile = emitProfiledOpcode(dynamic ? op_resolve_global_dynamic : op_resolve_global);
    12831313        instructions().append(dst->index());
    12841314        instructions().append(addConstant(property));
    12851315        instructions().append(0);
    12861316        instructions().append(0);
    1287         if (requiresDynamicChecks)
    1288             instructions().append(depth);
     1317        if (dynamic)
     1318            instructions().append(resolveResult.depth());
    12891319        instructions().append(profile);
    12901320        return dst;
    12911321    }
    1292 
    1293     if (requiresDynamicChecks) {
    1294         // If we get here we have eval nested inside a |with| just give up
    1295         ValueProfile* profile = emitProfiledOpcode(op_resolve);
     1322       
     1323    if (resolveResult.type() == ResolveResult::Dynamic && resolveResult.depth()) {
     1324        // In this case we are at least able to drop a few scope chains from the
     1325        // lookup chain, although we still need to hash from then on.
     1326        ValueProfile* profile = emitProfiledOpcode(op_resolve_skip);
    12961327        instructions().append(dst->index());
    12971328        instructions().append(addConstant(property));
     1329        instructions().append(resolveResult.depth());
    12981330        instructions().append(profile);
    12991331        return dst;
    13001332    }
    13011333
    1302     if (index != missingSymbolMarker()) {
    1303         // Directly index the property lookup across multiple scopes.
    1304         return emitGetScopedVar(dst, depth, index, globalObject);
    1305     }
    1306 
    1307     // In this case we are at least able to drop a few scope chains from the
    1308     // lookup chain, although we still need to hash from then on.
    1309     ValueProfile* profile = emitProfiledOpcode(op_resolve_skip);
     1334    ValueProfile* profile = emitProfiledOpcode(op_resolve);
    13101335    instructions().append(dst->index());
    13111336    instructions().append(addConstant(property));
    1312     instructions().append(depth);
    13131337    instructions().append(profile);
    13141338    return dst;
    13151339}
    13161340
    1317 RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject)
    1318 {
    1319     if (globalObject) {
    1320         if (m_lastOpcodeID == op_put_global_var) {
    1321             int dstIndex;
    1322             int srcIndex;
    1323             retrieveLastUnaryOp(dstIndex, srcIndex);
    1324            
    1325             if (dstIndex == index && srcIndex == dst->index())
    1326                 return dst;
    1327         }
    1328 
    1329         ValueProfile* profile = emitProfiledOpcode(op_get_global_var);
    1330         instructions().append(dst->index());
    1331         instructions().append(index);
    1332         instructions().append(profile);
    1333         return dst;
    1334     }
    1335 
    1336     ValueProfile* profile = emitProfiledOpcode(op_get_scoped_var);
     1341RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)
     1342{
     1343    if (resolveResult.isGlobal() && !resolveResult.isDynamic())
     1344        // Global object is the base
     1345        return emitLoad(dst, JSValue(resolveResult.globalObject()));
     1346
     1347    // We can't optimise at all :-(
     1348    ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
    13371349    instructions().append(dst->index());
    1338     instructions().append(index);
    1339     instructions().append(depth);
     1350    instructions().append(addConstant(property));
     1351    instructions().append(false);
    13401352    instructions().append(profile);
    13411353    return dst;
    13421354}
    13431355
    1344 RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue globalObject)
    1345 {
    1346     if (globalObject) {
    1347         emitOpcode(op_put_global_var);
    1348         instructions().append(index);
    1349         instructions().append(value->index());
    1350         return value;
    1351     }
    1352     emitOpcode(op_put_scoped_var);
    1353     instructions().append(index);
    1354     instructions().append(depth);
    1355     instructions().append(value->index());
    1356     return value;
    1357 }
    1358 
    1359 RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
    1360 {
    1361     size_t depth = 0;
    1362     int index = 0;
    1363     JSObject* globalObject = 0;
    1364     bool requiresDynamicChecks = false;
    1365     findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
    1366     if (!globalObject || requiresDynamicChecks) {
    1367         // We can't optimise at all :-(
    1368         ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
     1356RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const ResolveResult& resolveResult, const Identifier& property)
     1357{
     1358    if (!m_codeBlock->isStrictMode())
     1359        return emitResolveBase(dst, resolveResult, property);
     1360
     1361    if (resolveResult.isGlobal() && !resolveResult.isDynamic()) {
     1362        // Global object is the base
     1363        RefPtr<RegisterID> result = emitLoad(dst, JSValue(resolveResult.globalObject()));
     1364        emitOpcode(op_ensure_property_exists);
    13691365        instructions().append(dst->index());
    13701366        instructions().append(addConstant(property));
    1371         instructions().append(false);
    1372         instructions().append(profile);
    1373         return dst;
    1374     }
    1375 
    1376     // Global object is the base
    1377     return emitLoad(dst, JSValue(globalObject));
    1378 }
    1379 
    1380 RegisterID* BytecodeGenerator::emitResolveBaseForPut(RegisterID* dst, const Identifier& property)
    1381 {
    1382     if (!m_codeBlock->isStrictMode())
    1383         return emitResolveBase(dst, property);
    1384     size_t depth = 0;
    1385     int index = 0;
    1386     JSObject* globalObject = 0;
    1387     bool requiresDynamicChecks = false;
    1388     findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject);
    1389     if (!globalObject || requiresDynamicChecks) {
    1390         // We can't optimise at all :-(
    1391         ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
    1392         instructions().append(dst->index());
    1393         instructions().append(addConstant(property));
    1394         instructions().append(true);
    1395         instructions().append(profile);
    1396         return dst;
    1397     }
    1398    
    1399     // Global object is the base
    1400     RefPtr<RegisterID> result = emitLoad(dst, JSValue(globalObject));
    1401     emitOpcode(op_ensure_property_exists);
     1367        return result.get();
     1368    }
     1369
     1370    // We can't optimise at all :-(
     1371    ValueProfile* profile = emitProfiledOpcode(op_resolve_base);
    14021372    instructions().append(dst->index());
    14031373    instructions().append(addConstant(property));
    1404     return result.get();
    1405 }
    1406 
    1407 RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
    1408 {
    1409     size_t depth = 0;
    1410     int index = 0;
    1411     JSObject* globalObject = 0;
    1412     bool requiresDynamicChecks = false;
    1413     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
    1414         // We can't optimise at all :-(
    1415         ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
    1416         instructions().append(baseDst->index());
     1374    instructions().append(true);
     1375    instructions().append(profile);
     1376    return dst;
     1377}
     1378
     1379RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const ResolveResult& resolveResult, const Identifier& property)
     1380{
     1381    if (resolveResult.isGlobal() && !resolveResult.isDynamic()) {
     1382        // Global object is the base
     1383        emitLoad(baseDst, JSValue(resolveResult.globalObject()));
     1384
     1385        if (resolveResult.isStatic()) {
     1386            // Directly index the property lookup across multiple scopes.
     1387            emitGetStaticVar(propDst, resolveResult);
     1388            return baseDst;
     1389        }
     1390
     1391        if (shouldAvoidResolveGlobal()) {
     1392            ValueProfile* profile = emitProfiledOpcode(op_resolve);
     1393            instructions().append(propDst->index());
     1394            instructions().append(addConstant(property));
     1395            instructions().append(profile);
     1396            return baseDst;
     1397        }
     1398
     1399#if ENABLE(JIT)
     1400        m_codeBlock->addGlobalResolveInfo(instructions().size());
     1401#endif
     1402#if ENABLE(INTERPRETER)
     1403        m_codeBlock->addGlobalResolveInstruction(instructions().size());
     1404#endif
     1405        ValueProfile* profile = emitProfiledOpcode(op_resolve_global);
    14171406        instructions().append(propDst->index());
    14181407        instructions().append(addConstant(property));
     1408        instructions().append(0);
     1409        instructions().append(0);
    14191410        instructions().append(profile);
    14201411        return baseDst;
    14211412    }
    14221413
    1423     bool forceGlobalResolve = false;
    1424 
    1425     // Global object is the base
    1426     emitLoad(baseDst, JSValue(globalObject));
    1427 
    1428     if (index != missingSymbolMarker() && !forceGlobalResolve) {
    1429         // Directly index the property lookup across multiple scopes.
    1430         emitGetScopedVar(propDst, depth, index, globalObject);
    1431         return baseDst;
    1432     }
    1433     if (shouldAvoidResolveGlobal()) {
    1434         ValueProfile* profile = emitProfiledOpcode(op_resolve);
    1435         instructions().append(propDst->index());
    1436         instructions().append(addConstant(property));
    1437         instructions().append(profile);
    1438         return baseDst;
    1439     }
    1440 #if ENABLE(JIT)
    1441     m_codeBlock->addGlobalResolveInfo(instructions().size());
    1442 #endif
    1443 #if ENABLE(INTERPRETER)
    1444     m_codeBlock->addGlobalResolveInstruction(instructions().size());
    1445 #endif
    1446     ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
     1414
     1415
     1416
     1417    ValueProfile* profile = emitProfiledOpcode(op_resolve_with_base);
     1418    instructions().append(baseDst->index());
    14471419    instructions().append(propDst->index());
    14481420    instructions().append(addConstant(property));
    1449     instructions().append(0);
    1450     instructions().append(0);
    1451     if (requiresDynamicChecks)
    1452         instructions().append(depth);
    14531421    instructions().append(profile);
    14541422    return baseDst;
    14551423}
    14561424
    1457 RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
    1458 {
    1459     size_t depth = 0;
    1460     int index = 0;
    1461     JSObject* globalObject = 0;
    1462     bool requiresDynamicChecks = false;
    1463     if (!findScopedProperty(property, index, depth, false, requiresDynamicChecks, globalObject) || !globalObject || requiresDynamicChecks) {
     1425RegisterID* BytecodeGenerator::emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const ResolveResult& resolveResult, const Identifier& property)
     1426{
     1427    if (resolveResult.isStatic()) {
     1428        emitLoad(baseDst, jsUndefined());
     1429        emitGetStaticVar(propDst, resolveResult);
     1430        return baseDst;
     1431    }
     1432
     1433    if (resolveResult.type() == ResolveResult::Dynamic) {
    14641434        // We can't optimise at all :-(
    14651435        ValueProfile* profile = emitProfiledOpcode(op_resolve_with_this);
     
    14711441    }
    14721442
    1473     bool forceGlobalResolve = false;
    1474 
    1475     // Global object is the base
    14761443    emitLoad(baseDst, jsUndefined());
    1477 
    1478     if (index != missingSymbolMarker() && !forceGlobalResolve) {
    1479         // Directly index the property lookup across multiple scopes.
    1480         emitGetScopedVar(propDst, depth, index, globalObject);
    1481         return baseDst;
    1482     }
    1483     if (shouldAvoidResolveGlobal()) {
    1484         ValueProfile* profile = emitProfiledOpcode(op_resolve);
    1485         instructions().append(propDst->index());
    1486         instructions().append(addConstant(property));
     1444    return emitResolve(propDst, resolveResult, property);
     1445}
     1446
     1447RegisterID* BytecodeGenerator::emitGetStaticVar(RegisterID* dst, const ResolveResult& resolveResult)
     1448{
     1449    ValueProfile* profile = 0;
     1450
     1451    switch (resolveResult.type()) {
     1452    case ResolveResult::Register:
     1453    case ResolveResult::ReadOnlyRegister:
     1454        if (dst == ignoredResult())
     1455            return 0;
     1456        return moveToDestinationIfNeeded(dst, resolveResult.local());
     1457
     1458    case ResolveResult::Lexical:
     1459    case ResolveResult::ReadOnlyLexical:
     1460        profile = emitProfiledOpcode(op_get_scoped_var);
     1461        instructions().append(dst->index());
     1462        instructions().append(resolveResult.index());
     1463        instructions().append(resolveResult.depth());
    14871464        instructions().append(profile);
    1488         return baseDst;
    1489     }
    1490 #if ENABLE(JIT)
    1491     m_codeBlock->addGlobalResolveInfo(instructions().size());
    1492 #endif
    1493 #if ENABLE(INTERPRETER)
    1494     m_codeBlock->addGlobalResolveInstruction(instructions().size());
    1495 #endif
    1496     ValueProfile* profile = emitProfiledOpcode(requiresDynamicChecks ? op_resolve_global_dynamic : op_resolve_global);
    1497     instructions().append(propDst->index());
    1498     instructions().append(addConstant(property));
    1499     instructions().append(0);
    1500     instructions().append(0);
    1501     if (requiresDynamicChecks)
    1502         instructions().append(depth);
    1503     instructions().append(profile);
    1504     return baseDst;
     1465        return dst;
     1466
     1467    case ResolveResult::IndexedGlobal:
     1468    case ResolveResult::ReadOnlyIndexedGlobal:
     1469        if (m_lastOpcodeID == op_put_global_var) {
     1470            int dstIndex;
     1471            int srcIndex;
     1472            retrieveLastUnaryOp(dstIndex, srcIndex);
     1473            if (dstIndex == resolveResult.index() && srcIndex == dst->index())
     1474                return dst;
     1475        }
     1476
     1477        profile = emitProfiledOpcode(op_get_global_var);
     1478        instructions().append(dst->index());
     1479        instructions().append(resolveResult.index());
     1480        instructions().append(profile);
     1481        return dst;
     1482
     1483    default:
     1484        ASSERT_NOT_REACHED();
     1485        return 0;
     1486    }
     1487}
     1488
     1489RegisterID* BytecodeGenerator::emitPutStaticVar(const ResolveResult& resolveResult, RegisterID* value)
     1490{
     1491    switch (resolveResult.type()) {
     1492    case ResolveResult::Register:
     1493    case ResolveResult::ReadOnlyRegister:
     1494        return moveToDestinationIfNeeded(resolveResult.local(), value);
     1495
     1496    case ResolveResult::Lexical:
     1497    case ResolveResult::ReadOnlyLexical:
     1498        emitOpcode(op_put_scoped_var);
     1499        instructions().append(resolveResult.index());
     1500        instructions().append(resolveResult.depth());
     1501        instructions().append(value->index());
     1502        return value;
     1503
     1504    case ResolveResult::IndexedGlobal:
     1505    case ResolveResult::ReadOnlyIndexedGlobal:
     1506        emitOpcode(op_put_global_var);
     1507        instructions().append(resolveResult.index());
     1508        instructions().append(value->index());
     1509        return value;
     1510
     1511    default:
     1512        ASSERT_NOT_REACHED();
     1513        return 0;
     1514    }
    15051515}
    15061516
     
    23852395bool BytecodeGenerator::isArgumentNumber(const Identifier& ident, int argumentNumber)
    23862396{
    2387     RegisterID* registerID = registerFor(ident);
     2397    RegisterID* registerID = resolve(ident).local();
    23882398    if (!registerID || registerID->index() >= 0)
    23892399         return 0;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r106255 r106478  
    22 * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
    33 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca>
     4 * Copyright (C) 2012 Igalia, S.L.
    45 *
    56 * Redistribution and use in source and binary forms, with or without
     
    8687    };
    8788
     89    class ResolveResult {
     90    public:
     91        enum Flags {
     92            // The property is locally bound, in a register.
     93            RegisterFlag = 0x1,
     94            // We need to traverse the scope chain at runtime, checking for
     95            // non-strict eval and/or `with' nodes.
     96            DynamicFlag = 0x2,
     97            // The property was resolved to a definite location, and the
     98            // identifier is not needed any more.
     99            StaticFlag = 0x4,
     100            // Once we have the base object, the property will be located at a
     101            // known index.
     102            IndexedFlag = 0x8,
     103            // Skip some number of objects in the scope chain, given by "depth".
     104            ScopedFlag = 0x10,
     105            // The resolved binding is immutable.
     106            ReadOnlyFlag = 0x20,
     107            // The base object is the global object.
     108            GlobalFlag = 0x40
     109        };
     110        enum Type {
     111            // The property is local, and stored in a register.
     112            Register = RegisterFlag | StaticFlag,
     113            // A read-only local, created by "const".
     114            ReadOnlyRegister = RegisterFlag | ReadOnlyFlag | StaticFlag,
     115            // The property is statically scoped free variable. Its coordinates
     116            // are in "index" and "depth".
     117            Lexical = IndexedFlag | ScopedFlag | StaticFlag,
     118            // A read-only Lexical, created by "const".
     119            ReadOnlyLexical = IndexedFlag | ScopedFlag | ReadOnlyFlag | StaticFlag,
     120            // The property was not bound lexically, so at runtime we should
     121            // look directly in the global object.
     122            Global = GlobalFlag,
     123            // Like Global, but we could actually resolve the property to a
     124            // DontDelete property in the global object, for instance, any
     125            // binding created with "var" at the top level. At runtime we'll
     126            // just index into the global object.
     127            IndexedGlobal = IndexedFlag | GlobalFlag | StaticFlag,
     128            // Like IndexedGlobal, but the property is also read-only, like NaN,
     129            // Infinity, or undefined.
     130            ReadOnlyIndexedGlobal = IndexedFlag | ReadOnlyFlag | GlobalFlag | StaticFlag,
     131            // The property could not be resolved statically, due to the
     132            // presence of `with' blocks. At runtime we'll have to walk the
     133            // scope chain. ScopedFlag is set to indicate that "depth" will
     134            // hold some number of nodes to skip in the scope chain, before
     135            // beginning the search.
     136            Dynamic = DynamicFlag | ScopedFlag,
     137            // The property was located as a statically scoped free variable,
     138            // but while traversing the scope chain, there was an intermediate
     139            // activation that used non-strict `eval'. At runtime we'll have to
     140            // check for the absence of this property in those intervening
     141            // scopes.
     142            DynamicLexical = DynamicFlag | IndexedFlag | ScopedFlag,
     143            // Like ReadOnlyLexical, but with intervening non-strict `eval'.
     144            DynamicReadOnlyLexical = DynamicFlag | IndexedFlag | ScopedFlag | ReadOnlyFlag,
     145            // Like Global, but with intervening non-strict `eval'. As with
     146            // Dynamic, ScopeFlag is set to indicate that "depth" does indeed
     147            // store a number of frames to skip before doing the dynamic checks.
     148            DynamicGlobal = DynamicFlag | GlobalFlag | ScopedFlag,
     149            // Like IndexedGlobal, but with intervening non-strict `eval'.
     150            DynamicIndexedGlobal = DynamicFlag | IndexedFlag | GlobalFlag | ScopedFlag,
     151            // Like ReadOnlyIndexedGlobal, but with intervening non-strict
     152            // `eval'.
     153            DynamicReadOnlyIndexedGlobal = DynamicFlag | IndexedFlag | ReadOnlyFlag | GlobalFlag | ScopedFlag,
     154        };
     155
     156        static ResolveResult registerResolve(RegisterID *local, unsigned flags)
     157        {
     158            return ResolveResult(Register | flags, local, missingSymbolMarker(), 0, 0);
     159        }
     160        static ResolveResult dynamicResolve(size_t depth)
     161        {
     162            return ResolveResult(Dynamic, 0, missingSymbolMarker(), depth, 0);
     163        }
     164        static ResolveResult lexicalResolve(int index, size_t depth, unsigned flags)
     165        {
     166            unsigned type = (flags & DynamicFlag) ? DynamicLexical : Lexical;
     167            return ResolveResult(type | flags, 0, index, depth, 0);
     168        }
     169        static ResolveResult indexedGlobalResolve(int index, JSObject *globalObject, unsigned flags)
     170        {
     171            return ResolveResult(IndexedGlobal | flags, 0, index, 0, globalObject);
     172        }
     173        static ResolveResult dynamicIndexedGlobalResolve(int index, size_t depth, JSObject *globalObject, unsigned flags)
     174        {
     175            return ResolveResult(DynamicIndexedGlobal | flags, 0, index, depth, globalObject);
     176        }
     177        static ResolveResult globalResolve(JSObject *globalObject)
     178        {
     179            return ResolveResult(Global, 0, missingSymbolMarker(), 0, globalObject);
     180        }
     181        static ResolveResult dynamicGlobalResolve(size_t dynamicDepth, JSObject *globalObject)
     182        {
     183            return ResolveResult(DynamicGlobal, 0, missingSymbolMarker(), dynamicDepth, globalObject);
     184        }
     185
     186        unsigned type() const { return m_type; }
     187        // Returns the register corresponding to a local variable, or 0 if no
     188        // such register exists. Registers returned by ResolveResult::local() do
     189        // not require explicit reference counting.
     190        RegisterID* local() const { return m_local; }
     191        int index() const { ASSERT (isIndexed() || isRegister()); return m_index; }
     192        size_t depth() const { ASSERT(isScoped()); return m_depth; }
     193        JSObject* globalObject() const { ASSERT(isGlobal()); ASSERT(m_globalObject); return m_globalObject; }
     194
     195        bool isRegister() const { return m_type & RegisterFlag; }
     196        bool isDynamic() const { return m_type & DynamicFlag; }
     197        bool isStatic() const { return m_type & StaticFlag; }
     198        bool isIndexed() const { return m_type & IndexedFlag; }
     199        bool isScoped() const { return m_type & ScopedFlag; }
     200        bool isReadOnly() const { return (m_type & ReadOnlyFlag) && !isDynamic(); }
     201        bool isGlobal() const { return m_type & GlobalFlag; }
     202
     203    private:
     204        ResolveResult(unsigned type, RegisterID* local, int index, size_t depth, JSObject* globalObject)
     205            : m_type(type)
     206            , m_index(index)
     207            , m_local(local)
     208            , m_depth(depth)
     209            , m_globalObject(globalObject)
     210        {
     211#ifndef NDEBUG
     212            checkValidity();
     213#endif
     214        }
     215
     216#ifndef NDEBUG
     217        void checkValidity();
     218#endif
     219
     220        unsigned m_type;
     221        int m_index; // Index in scope, if IndexedFlag is set
     222        RegisterID* m_local; // Local register, if RegisterFlag is set
     223        size_t m_depth; // Depth in scope chain, if ScopedFlag is set
     224        JSObject* m_globalObject; // If GlobalFlag is set.
     225    };
     226
    88227    class BytecodeGenerator {
    89228        WTF_MAKE_FAST_ALLOCATED;
     
    108247        JSObject* generate();
    109248
    110         // Returns the register corresponding to a local variable, or 0 if no
    111         // such register exists. Registers returned by registerFor do not
    112         // require explicit reference counting.
    113         RegisterID* registerFor(const Identifier&);
    114 
    115249        bool isArgumentNumber(const Identifier&, int);
    116250
     
    120254        RegisterID* uncheckedRegisterForArguments();
    121255
    122         // Behaves as registerFor does, but ignores dynamic scope as
     256        // Resolve an identifier, given the current compile-time scope chain.
     257        ResolveResult resolve(const Identifier&);
     258        // Behaves as resolve does, but ignores dynamic scope as
    123259        // dynamic scope should not interfere with const initialisation
    124         RegisterID* constRegisterFor(const Identifier&);
    125 
    126         // Searches the scope chain in an attempt to  statically locate the requested
    127         // property.  Returns false if for any reason the property cannot be safely
    128         // optimised at all.  Otherwise it will return the index and depth of the
    129         // VariableObject that defines the property.  If the property cannot be found
    130         // statically, depth will contain the depth of the scope chain where dynamic
    131         // lookup must begin.
    132         bool findScopedProperty(const Identifier&, int& index, size_t& depth, bool forWriting, bool& includesDynamicScopes, JSObject*& globalObject);
     260        ResolveResult resolveConstDecl(const Identifier&);
    133261
    134262        // Returns the register storing "this"
     
    310438        RegisterID* emitIn(RegisterID* dst, RegisterID* property, RegisterID* base) { return emitBinaryOp(op_in, dst, property, base, OperandTypes()); }
    311439
    312         RegisterID* emitResolve(RegisterID* dst, const Identifier& property);
    313         RegisterID* emitGetScopedVar(RegisterID* dst, size_t skip, int index, JSValue globalObject);
    314         RegisterID* emitPutScopedVar(size_t skip, int index, RegisterID* value, JSValue globalObject);
    315 
    316         RegisterID* emitResolveBase(RegisterID* dst, const Identifier& property);
    317         RegisterID* emitResolveBaseForPut(RegisterID* dst, const Identifier& property);
    318         RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
    319         RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const Identifier& property);
     440        RegisterID* emitGetStaticVar(RegisterID* dst, const ResolveResult&);
     441        RegisterID* emitPutStaticVar(const ResolveResult&, RegisterID* value);
     442
     443        RegisterID* emitResolve(RegisterID* dst, const ResolveResult&, const Identifier& property);
     444        RegisterID* emitResolveBase(RegisterID* dst, const ResolveResult&, const Identifier& property);
     445        RegisterID* emitResolveBaseForPut(RegisterID* dst, const ResolveResult&, const Identifier& property);
     446        RegisterID* emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property);
     447        RegisterID* emitResolveWithThis(RegisterID* baseDst, RegisterID* propDst, const ResolveResult&, const Identifier& property);
    320448
    321449        void emitMethodCheck();
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r106255 r106478  
    66*  Copyright (C) 2007 Maks Orlovich
    77*  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
     8 * Copyright (C) 2012 Igalia, S.L.
    89*
    910*  This library is free software; you can redistribute it and/or
     
    147148RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    148149{
    149     if (RegisterID* local = generator.registerFor(m_ident)) {
     150    ResolveResult resolveResult = generator.resolve(m_ident);
     151    if (RegisterID* local = resolveResult.local()) {
    150152        if (dst == generator.ignoredResult())
    151153            return 0;
     
    154156   
    155157    generator.emitExpressionInfo(m_startOffset + m_ident.length(), m_ident.length(), 0);
    156     return generator.emitResolve(generator.finalDestination(dst), m_ident);
     158    return generator.emitResolve(generator.finalDestination(dst), resolveResult, m_ident);
    157159}
    158160
     
    399401    CallArguments callArguments(generator, m_args);
    400402    generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0);
    401     generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.propertyNames().eval);
     403    generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), generator.resolve(generator.propertyNames().eval), generator.propertyNames().eval);
    402404    return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
    403405}
     
    417419RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    418420{
    419     if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) {
    420         RefPtr<RegisterID> function = generator.emitMove(generator.tempDestination(dst), local.get());
     421    ResolveResult resolveResult = generator.resolve(m_ident);
     422
     423    if (RegisterID* local = resolveResult.local()) {
     424        RefPtr<RegisterID> func = generator.emitMove(generator.tempDestination(dst), local);
    421425        CallArguments callArguments(generator, m_args);
    422426        generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    423         return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), function.get(), callArguments, divot(), startOffset(), endOffset());
    424     }
    425 
    426     int index = 0;
    427     size_t depth = 0;
    428     JSObject* globalObject = 0;
    429     bool requiresDynamicChecks = false;
    430     if (generator.findScopedProperty(m_ident, index, depth, false, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
    431         RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
     427        return generator.emitCall(generator.finalDestinationOrIgnored(dst, callArguments.thisRegister()), func.get(), callArguments, divot(), startOffset(), endOffset());
     428    }
     429
     430    if (resolveResult.isStatic()) {
     431        RefPtr<RegisterID> func = generator.newTemporary();
    432432        CallArguments callArguments(generator, m_args);
     433        generator.emitGetStaticVar(func.get(), resolveResult);
    433434        generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    434435        return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
     
    438439    CallArguments callArguments(generator, m_args);
    439440    int identifierStart = divot() - startOffset();
     441
    440442    generator.emitExpressionInfo(identifierStart + m_ident.length(), m_ident.length(), 0);
    441     generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), m_ident);
     443    generator.emitResolveWithThis(callArguments.thisRegister(), func.get(), resolveResult, m_ident);
    442444    return generator.emitCall(generator.finalDestinationOrIgnored(dst, func.get()), func.get(), callArguments, divot(), startOffset(), endOffset());
    443445}
     
    603605RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    604606{
    605     if (RegisterID* local = generator.registerFor(m_ident)) {
    606         if (generator.isLocalConstant(m_ident)) {
     607    ResolveResult resolveResult = generator.resolve(m_ident);
     608
     609    if (RegisterID* local = resolveResult.local()) {
     610        if (resolveResult.isReadOnly()) {
    607611            if (dst == generator.ignoredResult())
    608612                return 0;
    609613            return generator.emitToJSNumber(generator.finalDestination(dst), local);
    610614        }
    611 
    612615        if (dst == generator.ignoredResult())
    613616            return emitPreIncOrDec(generator, local, m_operator);
     
    615618    }
    616619
    617     int index = 0;
    618     size_t depth = 0;
    619     JSObject* globalObject = 0;
    620     bool requiresDynamicChecks = false;
    621     if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
    622         RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject);
     620    if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
     621        RefPtr<RegisterID> value = generator.emitGetStaticVar(generator.newTemporary(), resolveResult);
    623622        RegisterID* oldValue;
    624623        if (dst == generator.ignoredResult()) {
     
    628627            oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
    629628        }
    630         generator.emitPutScopedVar(depth, index, value.get(), globalObject);
     629        generator.emitPutStaticVar(resolveResult, value.get());
    631630        return oldValue;
    632631    }
    633 
     632   
    634633    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    635634    RefPtr<RegisterID> value = generator.newTemporary();
    636     RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident);
     635    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), resolveResult, m_ident);
    637636    RegisterID* oldValue;
    638637    if (dst == generator.ignoredResult()) {
     
    706705RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    707706{
    708     if (generator.registerFor(m_ident))
     707    ResolveResult resolveResult = generator.resolve(m_ident);
     708    if (resolveResult.isRegister())
    709709        return generator.emitLoad(generator.finalDestination(dst), false);
    710710
    711711    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    712     RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
     712    RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident);
    713713    return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident);
    714714}
     
    761761RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    762762{
    763     if (RegisterID* local = generator.registerFor(m_ident)) {
     763    ResolveResult resolveResult = generator.resolve(m_ident);
     764    if (RegisterID* local = resolveResult.local()) {
    764765        if (dst == generator.ignoredResult())
    765766            return 0;
     
    767768    }
    768769
    769     RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident);
     770    RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), resolveResult, m_ident);
    770771    generator.emitGetById(scratch.get(), scratch.get(), m_ident);
    771772    if (dst == generator.ignoredResult())
     
    790791RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    791792{
    792     if (RegisterID* local = generator.registerFor(m_ident)) {
     793    ResolveResult resolveResult = generator.resolve(m_ident);
     794    if (RegisterID* local = resolveResult.local()) {
    793795        if (generator.isLocalConstant(m_ident)) {
    794796            if (dst == generator.ignoredResult())
     
    797799            return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes());
    798800        }
    799 
    800801        emitPreIncOrDec(generator, local, m_operator);
    801802        return generator.moveToDestinationIfNeeded(dst, local);
    802803    }
    803804
    804     int index = 0;
    805     size_t depth = 0;
    806     JSObject* globalObject = 0;
    807     bool requiresDynamicChecks = false;
    808     if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
    809         RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
     805    if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
     806        RefPtr<RegisterID> propDst = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
    810807        emitPreIncOrDec(generator, propDst.get(), m_operator);
    811         generator.emitPutScopedVar(depth, index, propDst.get(), globalObject);
     808        generator.emitPutStaticVar(resolveResult, propDst.get());
    812809        return generator.moveToDestinationIfNeeded(dst, propDst.get());
    813810    }
     
    815812    generator.emitExpressionInfo(divot(), startOffset(), endOffset());
    816813    RefPtr<RegisterID> propDst = generator.tempDestination(dst);
    817     RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident);
     814    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), resolveResult, m_ident);
    818815    emitPreIncOrDec(generator, propDst.get(), m_operator);
    819816    generator.emitPutById(base.get(), m_ident, propDst.get());
     
    12031200RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    12041201{
    1205     if (RegisterID* local = generator.registerFor(m_ident)) {
    1206         if (generator.isLocalConstant(m_ident)) {
     1202    ResolveResult resolveResult = generator.resolve(m_ident);
     1203
     1204    if (RegisterID *local = resolveResult.local()) {
     1205        if (resolveResult.isReadOnly())
    12071206            return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    1208         }
    12091207       
    12101208        if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
     
    12201218    }
    12211219
    1222     int index = 0;
    1223     size_t depth = 0;
    1224     JSObject* globalObject = 0;
    1225     bool requiresDynamicChecks = false;
    1226     if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
    1227         RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject);
     1220    if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
     1221        RefPtr<RegisterID> src1 = generator.emitGetStaticVar(generator.tempDestination(dst), resolveResult);
    12281222        RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
    1229         generator.emitPutScopedVar(depth, index, result, globalObject);
     1223        generator.emitPutStaticVar(resolveResult, result);
    12301224        return result;
    12311225    }
     
    12331227    RefPtr<RegisterID> src1 = generator.tempDestination(dst);
    12341228    generator.emitExpressionInfo(divot() - startOffset() + m_ident.length(), m_ident.length(), 0);
    1235     RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident);
     1229    RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), resolveResult, m_ident);
    12361230    RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
    12371231    return generator.emitPutById(base.get(), m_ident, result);
     
    12421236RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
    12431237{
    1244     if (RegisterID* local = generator.registerFor(m_ident)) {
    1245         if (generator.isLocalConstant(m_ident))
     1238    ResolveResult resolveResult = generator.resolve(m_ident);
     1239
     1240    if (RegisterID *local = resolveResult.local()) {
     1241        if (resolveResult.isReadOnly())
    12461242            return generator.emitNode(dst, m_right);
    1247        
    12481243        RegisterID* result = generator.emitNode(local, m_right);
    12491244        return generator.moveToDestinationIfNeeded(dst, result);
    12501245    }
    12511246
    1252     int index = 0;
    1253     size_t depth = 0;
    1254     JSObject* globalObject = 0;
    1255     bool requiresDynamicChecks = false;
    1256     if (generator.findScopedProperty(m_ident, index, depth, true, requiresDynamicChecks, globalObject) && index != missingSymbolMarker() && !requiresDynamicChecks) {
     1247    if (resolveResult.isStatic() && !resolveResult.isReadOnly()) {
    12571248        if (dst == generator.ignoredResult())
    12581249            dst = 0;
    12591250        RegisterID* value = generator.emitNode(dst, m_right);
    1260         generator.emitPutScopedVar(depth, index, value, globalObject);
     1251        generator.emitPutStaticVar(resolveResult, value);
    12611252        return value;
    12621253    }
    12631254
    1264     RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), m_ident);
     1255    RefPtr<RegisterID> base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, m_ident);
    12651256    if (dst == generator.ignoredResult())
    12661257        dst = 0;
     
    13501341RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
    13511342{
     1343    ResolveResult resolveResult = generator.resolveConstDecl(m_ident);
     1344
    13521345    // FIXME: This code does not match the behavior of const in Firefox.
    1353     if (RegisterID* local = generator.constRegisterFor(m_ident)) {
     1346    if (RegisterID* local = resolveResult.local()) {
    13541347        if (!m_init)
    13551348            return local;
     
    13601353    RefPtr<RegisterID> value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined());
    13611354
    1362     ScopeChainIterator iter = generator.scopeChain()->begin();
    1363     ScopeChainIterator end = generator.scopeChain()->end();
    1364     size_t depth = 0;
    1365     for (; iter != end; ++iter, ++depth) {
    1366         JSObject* currentScope = iter->get();
    1367         if (!currentScope->isVariableObject())
    1368             continue;
    1369         JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope);
    1370         SymbolTableEntry entry = currentVariableObject->symbolTable().get(m_ident.impl());
    1371         if (entry.isNull())
    1372             continue;
    1373 
    1374         return generator.emitPutScopedVar(generator.scopeDepth() + depth, entry.getIndex(), value.get(), currentVariableObject->isGlobalObject() ? currentVariableObject : 0);
    1375     }
    1376 
     1355    if (resolveResult.isStatic())
     1356        return generator.emitPutStaticVar(resolveResult, value.get());
     1357   
    13771358    if (generator.codeType() != EvalCode)
    13781359        return value.get();
     
    13801361    // FIXME: While this code should only be hit in an eval block, it will assign
    13811362    // to the wrong base if m_ident exists in an intervening with scope.
    1382     RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident);
     1363    RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), resolveResult, m_ident);
    13831364    return generator.emitPutById(base.get(), m_ident, value.get());
    13841365}
     
    16511632    if (m_lexpr->isResolveNode()) {
    16521633        const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
    1653         propertyName = generator.registerFor(ident);
     1634        ResolveResult resolveResult = generator.resolve(ident);
     1635        propertyName = resolveResult.local();
    16541636        if (!propertyName) {
    16551637            propertyName = generator.newTemporary();
    16561638            RefPtr<RegisterID> protect = propertyName;
    1657             RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), ident);
     1639            RegisterID* base = generator.emitResolveBaseForPut(generator.newTemporary(), resolveResult, ident);
    16581640
    16591641            generator.emitExpressionInfo(divot(), startOffset(), endOffset());
Note: See TracChangeset for help on using the changeset viewer.