]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - bytecompiler/BytecodeGenerator.cpp
JavaScriptCore-584.tar.gz
[apple/javascriptcore.git] / bytecompiler / BytecodeGenerator.cpp
index cd89c1e7f7d892524a14fb109edb3123c9ab9794..b0a0877c15ba83b47b4dff470e37e487c99f3d1d 100644 (file)
@@ -31,6 +31,7 @@
 #include "BytecodeGenerator.h"
 
 #include "BatchedTransitionOptimizer.h"
 #include "BytecodeGenerator.h"
 
 #include "BatchedTransitionOptimizer.h"
+#include "PrototypeFunction.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
 #include "UString.h"
 #include "JSFunction.h"
 #include "Interpreter.h"
 #include "UString.h"
@@ -195,17 +196,10 @@ bool BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant, R
     return result.second;
 }
 
     return result.second;
 }
 
-void BytecodeGenerator::allocateConstants(size_t count)
+void BytecodeGenerator::preserveLastVar()
 {
 {
-    m_codeBlock->m_numConstants = count;
-    if (!count)
-        return;
-    
-    m_nextConstantIndex = m_calleeRegisters.size();
-
-    for (size_t i = 0; i < count; ++i)
-        newRegister();
-    m_lastConstant = &m_calleeRegisters.last();
+    if ((m_firstConstantIndex = m_calleeRegisters.size()) != 0)
+        m_lastVar = &m_calleeRegisters.last();
 }
 
 BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
 }
 
 BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, ProgramCodeBlock* codeBlock)
@@ -221,6 +215,8 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
     , m_baseScopeDepth(0)
     , m_codeType(GlobalCode)
     , m_nextGlobalIndex(-1)
     , m_baseScopeDepth(0)
     , m_codeType(GlobalCode)
     , m_nextGlobalIndex(-1)
+    , m_nextConstantOffset(0)
+    , m_globalConstantIndex(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     , m_lastOpcodeID(op_end)
     , m_emitNodeDepth(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     , m_lastOpcodeID(op_end)
     , m_emitNodeDepth(0)
@@ -260,35 +256,35 @@ BytecodeGenerator::BytecodeGenerator(ProgramNode* programNode, const Debugger* d
         m_nextGlobalIndex -= symbolTable->size();
 
         for (size_t i = 0; i < functionStack.size(); ++i) {
         m_nextGlobalIndex -= symbolTable->size();
 
         for (size_t i = 0; i < functionStack.size(); ++i) {
-            FuncDeclNode* funcDecl = functionStack[i].get();
-            globalObject->removeDirect(funcDecl->m_ident); // Make sure our new function is not shadowed by an old property.
-            emitNewFunction(addGlobalVar(funcDecl->m_ident, false), funcDecl);
+            FunctionBodyNode* function = functionStack[i];
+            globalObject->removeDirect(function->ident()); // Make sure our new function is not shadowed by an old property.
+            emitNewFunction(addGlobalVar(function->ident(), false), function);
         }
 
         Vector<RegisterID*, 32> newVars;
         for (size_t i = 0; i < varStack.size(); ++i)
         }
 
         Vector<RegisterID*, 32> newVars;
         for (size_t i = 0; i < varStack.size(); ++i)
-            if (!globalObject->hasProperty(exec, varStack[i].first))
-                newVars.append(addGlobalVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
+            if (!globalObject->hasProperty(exec, *varStack[i].first))
+                newVars.append(addGlobalVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant));
 
 
-        allocateConstants(programNode->neededConstants());
+        preserveLastVar();
 
         for (size_t i = 0; i < newVars.size(); ++i)
             emitLoad(newVars[i], jsUndefined());
     } else {
         for (size_t i = 0; i < functionStack.size(); ++i) {
 
         for (size_t i = 0; i < newVars.size(); ++i)
             emitLoad(newVars[i], jsUndefined());
     } else {
         for (size_t i = 0; i < functionStack.size(); ++i) {
-            FuncDeclNode* funcDecl = functionStack[i].get();
-            globalObject->putWithAttributes(exec, funcDecl->m_ident, funcDecl->makeFunction(exec, scopeChain.node()), DontDelete);
+            FunctionBodyNode* function = functionStack[i];
+            globalObject->putWithAttributes(exec, function->ident(), new (exec) JSFunction(exec, makeFunction(exec, function), scopeChain.node()), DontDelete);
         }
         for (size_t i = 0; i < varStack.size(); ++i) {
         }
         for (size_t i = 0; i < varStack.size(); ++i) {
-            if (globalObject->hasProperty(exec, varStack[i].first))
+            if (globalObject->hasProperty(exec, *varStack[i].first))
                 continue;
             int attributes = DontDelete;
             if (varStack[i].second & DeclarationStacks::IsConstant)
                 attributes |= ReadOnly;
                 continue;
             int attributes = DontDelete;
             if (varStack[i].second & DeclarationStacks::IsConstant)
                 attributes |= ReadOnly;
-            globalObject->putWithAttributes(exec, varStack[i].first, jsUndefined(), attributes);
+            globalObject->putWithAttributes(exec, *varStack[i].first, jsUndefined(), attributes);
         }
 
         }
 
-        allocateConstants(programNode->neededConstants());
+        preserveLastVar();
     }
 }
 
     }
 }
 
@@ -303,6 +299,8 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(0)
     , m_codeType(FunctionCode)
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(0)
     , m_codeType(FunctionCode)
+    , m_nextConstantOffset(0)
+    , m_globalConstantIndex(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     , m_lastOpcodeID(op_end)
     , m_emitNodeDepth(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     , m_lastOpcodeID(op_end)
     , m_emitNodeDepth(0)
@@ -329,23 +327,30 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
     } else
         emitOpcode(op_enter);
 
     } else
         emitOpcode(op_enter);
 
-    if (usesArguments)
-        emitOpcode(op_create_arguments);
+    if (usesArguments) {
+        emitOpcode(op_init_arguments);
+
+        // The debugger currently retrieves the arguments object from an activation rather than pulling
+        // it from a call frame.  In the long-term it should stop doing that (<rdar://problem/6911886>),
+        // but for now we force eager creation of the arguments object when debugging.
+        if (m_shouldEmitDebugHooks)
+            emitOpcode(op_create_arguments);
+    }
 
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i) {
 
     const DeclarationStacks::FunctionStack& functionStack = functionBody->functionStack();
     for (size_t i = 0; i < functionStack.size(); ++i) {
-        FuncDeclNode* funcDecl = functionStack[i].get();
-        const Identifier& ident = funcDecl->m_ident;
+        FunctionBodyNode* function = functionStack[i];
+        const Identifier& ident = function->ident();
         m_functions.add(ident.ustring().rep());
         m_functions.add(ident.ustring().rep());
-        emitNewFunction(addVar(ident, false), funcDecl);
+        emitNewFunction(addVar(ident, false), function);
     }
 
     const DeclarationStacks::VarStack& varStack = functionBody->varStack();
     for (size_t i = 0; i < varStack.size(); ++i)
     }
 
     const DeclarationStacks::VarStack& varStack = functionBody->varStack();
     for (size_t i = 0; i < varStack.size(); ++i)
-        addVar(varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
+        addVar(*varStack[i].first, varStack[i].second & DeclarationStacks::IsConstant);
 
 
-    const Identifier* parameters = functionBody->parameters();
-    size_t parameterCount = functionBody->parameterCount();
+    FunctionParameters& parameters = *functionBody->parameters();
+    size_t parameterCount = parameters.size();
     m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
     m_parameters.grow(1 + parameterCount); // reserve space for "this"
 
     m_nextParameterIndex = -RegisterFile::CallFrameHeaderSize - parameterCount - 1;
     m_parameters.grow(1 + parameterCount); // reserve space for "this"
 
@@ -362,7 +367,7 @@ BytecodeGenerator::BytecodeGenerator(FunctionBodyNode* functionBody, const Debug
     for (size_t i = 0; i < parameterCount; ++i)
         addParameter(parameters[i]);
 
     for (size_t i = 0; i < parameterCount; ++i)
         addParameter(parameters[i]);
 
-    allocateConstants(functionBody->neededConstants());
+    preserveLastVar();
 }
 
 BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
 }
 
 BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugger, const ScopeChain& scopeChain, SymbolTable* symbolTable, EvalCodeBlock* codeBlock)
@@ -377,6 +382,8 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(codeBlock->baseScopeDepth())
     , m_codeType(EvalCode)
     , m_dynamicScopeDepth(0)
     , m_baseScopeDepth(codeBlock->baseScopeDepth())
     , m_codeType(EvalCode)
+    , m_nextConstantOffset(0)
+    , m_globalConstantIndex(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     , m_lastOpcodeID(op_end)
     , m_emitNodeDepth(0)
     , m_globalData(&scopeChain.globalObject()->globalExec()->globalData())
     , m_lastOpcodeID(op_end)
     , m_emitNodeDepth(0)
@@ -390,7 +397,19 @@ BytecodeGenerator::BytecodeGenerator(EvalNode* evalNode, const Debugger* debugge
     codeBlock->setGlobalData(m_globalData);
     m_codeBlock->m_numParameters = 1; // Allocate space for "this"
 
     codeBlock->setGlobalData(m_globalData);
     m_codeBlock->m_numParameters = 1; // Allocate space for "this"
 
-    allocateConstants(evalNode->neededConstants());
+    const DeclarationStacks::FunctionStack& functionStack = evalNode->functionStack();
+    for (size_t i = 0; i < functionStack.size(); ++i)
+        m_codeBlock->addFunctionDecl(makeFunction(m_globalData, functionStack[i]));
+
+    const DeclarationStacks::VarStack& varStack = evalNode->varStack();
+    unsigned numVariables = varStack.size();
+    Vector<Identifier> variables;
+    variables.reserveCapacity(numVariables);
+    for (size_t i = 0; i < numVariables; ++i)
+        variables.append(*varStack[i].first);
+    codeBlock->adoptVariables(variables);
+
+    preserveLastVar();
 }
 
 RegisterID* BytecodeGenerator::addParameter(const Identifier& ident)
 }
 
 RegisterID* BytecodeGenerator::addParameter(const Identifier& ident)
@@ -424,6 +443,36 @@ RegisterID* BytecodeGenerator::registerFor(const Identifier& ident)
     if (entry.isNull())
         return 0;
 
     if (entry.isNull())
         return 0;
 
+    if (ident == propertyNames().arguments)
+        createArgumentsIfNecessary();
+
+    return &registerFor(entry.getIndex());
+}
+
+bool BytecodeGenerator::willResolveToArguments(const Identifier& ident)
+{
+    if (ident != propertyNames().arguments)
+        return false;
+    
+    if (!shouldOptimizeLocals())
+        return false;
+    
+    SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
+    if (entry.isNull())
+        return false;
+    
+    if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
+        return true;
+    
+    return false;
+}
+
+RegisterID* BytecodeGenerator::uncheckedRegisterForArguments()
+{
+    ASSERT(willResolveToArguments(propertyNames().arguments));
+
+    SymbolTableEntry entry = symbolTable().get(propertyNames().arguments.ustring().rep());
+    ASSERT(!entry.isNull());
     return &registerFor(entry.getIndex());
 }
 
     return &registerFor(entry.getIndex());
 }
 
@@ -433,7 +482,8 @@ RegisterID* BytecodeGenerator::constRegisterFor(const Identifier& ident)
         return 0;
 
     SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
         return 0;
 
     SymbolTableEntry entry = symbolTable().get(ident.ustring().rep());
-    ASSERT(!entry.isNull());
+    if (entry.isNull())
+        return 0;
 
     return &registerFor(entry.getIndex());
 }
 
     return &registerFor(entry.getIndex());
 }
@@ -484,7 +534,7 @@ PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, c
         m_labelScopes.removeLast();
 
     // Allocate new label scope.
         m_labelScopes.removeLast();
 
     // Allocate new label scope.
-    LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : 0); // Only loops have continue targets.
+    LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets.
     m_labelScopes.append(scope);
     return &m_labelScopes.last();
 }
     m_labelScopes.append(scope);
     return &m_labelScopes.last();
 }
@@ -558,14 +608,15 @@ void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp()
 
 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
 {
 
 PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target)
 {
+    size_t begin = instructions().size();
     emitOpcode(target->isForward() ? op_jmp : op_loop);
     emitOpcode(target->isForward() ? op_jmp : op_loop);
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
 {
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target)
 {
-    if (m_lastOpcodeID == op_less && !target->isForward()) {
+    if (m_lastOpcodeID == op_less) {
         int dstIndex;
         int src1Index;
         int src2Index;
         int dstIndex;
         int src1Index;
         int src2Index;
@@ -574,10 +625,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
-            emitOpcode(op_loop_if_less);
+
+            size_t begin = instructions().size();
+            emitOpcode(target->isForward() ? op_jless : op_loop_if_less);
             instructions().append(src1Index);
             instructions().append(src2Index);
             instructions().append(src1Index);
             instructions().append(src2Index);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) {
             return target;
         }
     } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) {
@@ -589,10 +642,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_loop_if_lesseq);
             instructions().append(src1Index);
             instructions().append(src2Index);
             emitOpcode(op_loop_if_lesseq);
             instructions().append(src1Index);
             instructions().append(src2Index);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
             return target;
         }
     } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
@@ -603,9 +658,11 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jeq_null);
             instructions().append(srcIndex);
             emitOpcode(op_jeq_null);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
             return target;
         }
     } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
@@ -616,24 +673,26 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jneq_null);
             instructions().append(srcIndex);
             emitOpcode(op_jneq_null);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     }
 
             return target;
         }
     }
 
+    size_t begin = instructions().size();
+
     emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
     instructions().append(cond->index());
     emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
     instructions().append(cond->index());
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
 {
     return target;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target)
 {
-    ASSERT(target->isForward());
-
-    if (m_lastOpcodeID == op_less) {
+    if (m_lastOpcodeID == op_less && target->isForward()) {
         int dstIndex;
         int src1Index;
         int src2Index;
         int dstIndex;
         int src1Index;
         int src2Index;
@@ -642,10 +701,29 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindBinaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jnless);
             instructions().append(src1Index);
             instructions().append(src2Index);
             emitOpcode(op_jnless);
             instructions().append(src1Index);
             instructions().append(src2Index);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
+            return target;
+        }
+    } else if (m_lastOpcodeID == op_lesseq && target->isForward()) {
+        int dstIndex;
+        int src1Index;
+        int src2Index;
+
+        retrieveLastBinaryOp(dstIndex, src1Index, src2Index);
+
+        if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
+            rewindBinaryOp();
+
+            size_t begin = instructions().size();
+            emitOpcode(op_jnlesseq);
+            instructions().append(src1Index);
+            instructions().append(src2Index);
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     } else if (m_lastOpcodeID == op_not) {
             return target;
         }
     } else if (m_lastOpcodeID == op_not) {
@@ -656,12 +734,14 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
-            emitOpcode(op_jtrue);
+
+            size_t begin = instructions().size();
+            emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true);
             instructions().append(srcIndex);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
             return target;
         }
-    } else if (m_lastOpcodeID == op_eq_null) {
+    } else if (m_lastOpcodeID == op_eq_null && target->isForward()) {
         int dstIndex;
         int srcIndex;
 
         int dstIndex;
         int srcIndex;
 
@@ -669,12 +749,14 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jneq_null);
             instructions().append(srcIndex);
             emitOpcode(op_jneq_null);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
             return target;
         }
-    } else if (m_lastOpcodeID == op_neq_null) {
+    } else if (m_lastOpcodeID == op_neq_null && target->isForward()) {
         int dstIndex;
         int srcIndex;
 
         int dstIndex;
         int srcIndex;
 
@@ -682,29 +764,42 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
 
         if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) {
             rewindUnaryOp();
+
+            size_t begin = instructions().size();
             emitOpcode(op_jeq_null);
             instructions().append(srcIndex);
             emitOpcode(op_jeq_null);
             instructions().append(srcIndex);
-            instructions().append(target->offsetFrom(instructions().size()));
+            instructions().append(target->bind(begin, instructions().size()));
             return target;
         }
     }
 
             return target;
         }
     }
 
-    emitOpcode(op_jfalse);
+    size_t begin = instructions().size();
+    emitOpcode(target->isForward() ? op_jfalse : op_loop_if_false);
     instructions().append(cond->index());
     instructions().append(cond->index());
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
     return target;
 }
 
-unsigned BytecodeGenerator::addConstant(FuncDeclNode* n)
+PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target)
 {
 {
-    // No need to explicitly unique function body nodes -- they're unique already.
-    return m_codeBlock->addFunction(n);
+    size_t begin = instructions().size();
+
+    emitOpcode(op_jneq_ptr);
+    instructions().append(cond->index());
+    instructions().append(m_scopeChain->globalObject()->d()->callFunction);
+    instructions().append(target->bind(begin, instructions().size()));
+    return target;
 }
 
 }
 
-unsigned BytecodeGenerator::addConstant(FuncExprNode* n)
+PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target)
 {
 {
-    // No need to explicitly unique function expression nodes -- they're unique already.
-    return m_codeBlock->addFunctionExpression(n);
+    size_t begin = instructions().size();
+
+    emitOpcode(op_jneq_ptr);
+    instructions().append(cond->index());
+    instructions().append(m_scopeChain->globalObject()->d()->applyFunction);
+    instructions().append(target->bind(begin, instructions().size()));
+    return target;
 }
 
 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
 }
 
 unsigned BytecodeGenerator::addConstant(const Identifier& ident)
@@ -717,24 +812,19 @@ unsigned BytecodeGenerator::addConstant(const Identifier& ident)
     return result.first->second;
 }
 
     return result.first->second;
 }
 
-RegisterID* BytecodeGenerator::addConstant(JSValuePtr v)
+RegisterID* BytecodeGenerator::addConstantValue(JSValue v)
 {
 {
-    pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValuePtr::encode(v), m_nextConstantIndex);
-    if (result.second) {
-        RegisterID& constant = m_calleeRegisters[m_nextConstantIndex];
-        
-        ++m_nextConstantIndex;
-
-        m_codeBlock->addConstantRegister(JSValuePtr(v));
-        return &constant;
-    }
+    int index = m_nextConstantOffset;
 
 
-    return &registerFor(result.first->second);
-}
+    pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset);
+    if (result.second) {
+        m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset);
+        ++m_nextConstantOffset;
+        m_codeBlock->addConstantRegister(JSValue(v));
+    } else
+        index = result.first->second;
 
 
-unsigned BytecodeGenerator::addUnexpectedConstant(JSValuePtr v)
-{
-    return m_codeBlock->addUnexpectedConstant(v);
+    return &m_constantPoolRegisters[index];
 }
 
 unsigned BytecodeGenerator::addRegExp(RegExp* r)
 }
 
 unsigned BytecodeGenerator::addRegExp(RegExp* r)
@@ -796,9 +886,8 @@ RegisterID* BytecodeGenerator::emitBinaryOp(OpcodeID opcodeID, RegisterID* dst,
     instructions().append(src2->index());
 
     if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
     instructions().append(src2->index());
 
     if (opcodeID == op_bitor || opcodeID == op_bitand || opcodeID == op_bitxor ||
-        opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub) {
+        opcodeID == op_add || opcodeID == op_mul || opcodeID == op_sub || opcodeID == op_div)
         instructions().append(types.toInt());
         instructions().append(types.toInt());
-    }
 
     return dst;
 }
 
     return dst;
 }
@@ -814,8 +903,8 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst
         if (src1->index() == dstIndex
             && src1->isTemporary()
             && m_codeBlock->isConstantRegisterIndex(src2->index())
         if (src1->index() == dstIndex
             && src1->isTemporary()
             && m_codeBlock->isConstantRegisterIndex(src2->index())
-            && m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()).isString()) {
-            const UString& value = asString(m_codeBlock->constantRegister(src2->index() - m_codeBlock->m_numVars).jsValue(m_scopeChain->globalObject()->globalExec()))->value();
+            && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) {
+            const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->tryGetValue();
             if (value == "undefined") {
                 rewindUnaryOp();
                 emitOpcode(op_is_undefined);
             if (value == "undefined") {
                 rewindUnaryOp();
                 emitOpcode(op_is_undefined);
@@ -879,7 +968,7 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number)
     // Later we can do the extra work to handle that like the other cases.
     if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
         return emitLoad(dst, jsNumber(globalData(), number));
     // Later we can do the extra work to handle that like the other cases.
     if (number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number))
         return emitLoad(dst, jsNumber(globalData(), number));
-    JSValuePtr& valueInMap = m_numberMap.add(number, noValue()).first->second;
+    JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second;
     if (!valueInMap)
         valueInMap = jsNumber(globalData(), number);
     return emitLoad(dst, valueInMap);
     if (!valueInMap)
         valueInMap = jsNumber(globalData(), number);
     return emitLoad(dst, valueInMap);
@@ -890,33 +979,17 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& ident
     JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second;
     if (!stringInMap)
         stringInMap = jsOwnedString(globalData(), identifier.ustring());
     JSString*& stringInMap = m_stringMap.add(identifier.ustring().rep(), 0).first->second;
     if (!stringInMap)
         stringInMap = jsOwnedString(globalData(), identifier.ustring());
-    return emitLoad(dst, JSValuePtr(stringInMap));
+    return emitLoad(dst, JSValue(stringInMap));
 }
 
 }
 
-RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValuePtr v)
+RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v)
 {
 {
-    RegisterID* constantID = addConstant(v);
+    RegisterID* constantID = addConstantValue(v);
     if (dst)
         return emitMove(dst, constantID);
     return constantID;
 }
 
     if (dst)
         return emitMove(dst, constantID);
     return constantID;
 }
 
-RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, bool b)
-{
-    emitOpcode(op_unexpected_load);
-    instructions().append(dst->index());
-    instructions().append(addUnexpectedConstant(jsBoolean(b)));
-    return dst;
-}
-
-RegisterID* BytecodeGenerator::emitUnexpectedLoad(RegisterID* dst, double d)
-{
-    emitOpcode(op_unexpected_load);
-    instructions().append(dst->index());
-    instructions().append(addUnexpectedConstant(jsNumber(globalData(), d)));
-    return dst;
-}
-
 bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject)
 {
     // Cases where we cannot statically optimize the lookup.
 bool BytecodeGenerator::findScopedProperty(const Identifier& property, int& index, size_t& stackDepth, bool forWriting, JSObject*& globalObject)
 {
     // Cases where we cannot statically optimize the lookup.
@@ -1037,7 +1110,7 @@ RegisterID* BytecodeGenerator::emitResolve(RegisterID* dst, const Identifier& pr
     return dst;
 }
 
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValuePtr globalObject)
+RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, int index, JSValue globalObject)
 {
     if (globalObject) {
         emitOpcode(op_get_global_var);
 {
     if (globalObject) {
         emitOpcode(op_get_global_var);
@@ -1054,7 +1127,7 @@ RegisterID* BytecodeGenerator::emitGetScopedVar(RegisterID* dst, size_t depth, i
     return dst;
 }
 
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValuePtr globalObject)
+RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, RegisterID* value, JSValue globalObject)
 {
     if (globalObject) {
         emitOpcode(op_put_global_var);
 {
     if (globalObject) {
         emitOpcode(op_put_global_var);
@@ -1072,34 +1145,77 @@ RegisterID* BytecodeGenerator::emitPutScopedVar(size_t depth, int index, Registe
 
 RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
 {
 
 RegisterID* BytecodeGenerator::emitResolveBase(RegisterID* dst, const Identifier& property)
 {
-    emitOpcode(op_resolve_base);
-    instructions().append(dst->index());
-    instructions().append(addConstant(property));
-    return dst;
+    size_t depth = 0;
+    int index = 0;
+    JSObject* globalObject = 0;
+    findScopedProperty(property, index, depth, false, globalObject);
+    if (!globalObject) {
+        // We can't optimise at all :-(
+        emitOpcode(op_resolve_base);
+        instructions().append(dst->index());
+        instructions().append(addConstant(property));
+        return dst;
+    }
+
+    // Global object is the base
+    return emitLoad(dst, JSValue(globalObject));
 }
 
 RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
 {
 }
 
 RegisterID* BytecodeGenerator::emitResolveWithBase(RegisterID* baseDst, RegisterID* propDst, const Identifier& property)
 {
-    emitOpcode(op_resolve_with_base);
-    instructions().append(baseDst->index());
+    size_t depth = 0;
+    int index = 0;
+    JSObject* globalObject = 0;
+    if (!findScopedProperty(property, index, depth, false, globalObject) || !globalObject) {
+        // We can't optimise at all :-(
+        emitOpcode(op_resolve_with_base);
+        instructions().append(baseDst->index());
+        instructions().append(propDst->index());
+        instructions().append(addConstant(property));
+        return baseDst;
+    }
+
+    bool forceGlobalResolve = false;
+    if (m_regeneratingForExceptionInfo) {
+#if ENABLE(JIT)
+        forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInfoAtBytecodeOffset(instructions().size());
+#else
+        forceGlobalResolve = m_codeBlockBeingRegeneratedFrom->hasGlobalResolveInstructionAtBytecodeOffset(instructions().size());
+#endif
+    }
+
+    // Global object is the base
+    emitLoad(baseDst, JSValue(globalObject));
+
+    if (index != missingSymbolMarker() && !forceGlobalResolve) {
+        // Directly index the property lookup across multiple scopes.
+        emitGetScopedVar(propDst, depth, index, globalObject);
+        return baseDst;
+    }
+
+#if ENABLE(JIT)
+    m_codeBlock->addGlobalResolveInfo(instructions().size());
+#else
+    m_codeBlock->addGlobalResolveInstruction(instructions().size());
+#endif
+    emitOpcode(op_resolve_global);
     instructions().append(propDst->index());
     instructions().append(propDst->index());
+    instructions().append(globalObject);
     instructions().append(addConstant(property));
     instructions().append(addConstant(property));
+    instructions().append(0);
+    instructions().append(0);
     return baseDst;
 }
 
     return baseDst;
 }
 
-RegisterID* BytecodeGenerator::emitResolveFunction(RegisterID* baseDst, RegisterID* funcDst, const Identifier& property)
+void BytecodeGenerator::emitMethodCheck()
 {
 {
-    emitOpcode(op_resolve_func);
-    instructions().append(baseDst->index());
-    instructions().append(funcDst->index());
-    instructions().append(addConstant(property));
-    return baseDst;
+    emitOpcode(op_method_check);
 }
 
 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
 #if ENABLE(JIT)
 }
 
 RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
 {
 #if ENABLE(JIT)
-    m_codeBlock->addStructureStubInfo(StructureStubInfo(op_get_by_id));
+    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_get_by_id));
 #else
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 #else
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
@@ -1118,7 +1234,7 @@ RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, co
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
 #if ENABLE(JIT)
 RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
 {
 #if ENABLE(JIT)
-    m_codeBlock->addStructureStubInfo(StructureStubInfo(op_put_by_id));
+    m_codeBlock->addStructureStubInfo(StructureStubInfo(access_put_by_id));
 #else
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
 #else
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 #endif
@@ -1163,6 +1279,19 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base,
 
 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
 
 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
+    for (size_t i = m_forInContextStack.size(); i > 0; i--) {
+        ForInContext& context = m_forInContextStack[i - 1];
+        if (context.propertyRegister == property) {
+            emitOpcode(op_get_by_pname);
+            instructions().append(dst->index());
+            instructions().append(base->index());
+            instructions().append(property->index());
+            instructions().append(context.expectedSubscriptRegister->index());
+            instructions().append(context.iterRegister->index());
+            instructions().append(context.indexRegister->index());
+            return dst;
+        }
+    }
     emitOpcode(op_get_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
     emitOpcode(op_get_by_val);
     instructions().append(dst->index());
     instructions().append(base->index());
@@ -1222,11 +1351,13 @@ RegisterID* BytecodeGenerator::emitNewArray(RegisterID* dst, ElementNode* elemen
     return dst;
 }
 
     return dst;
 }
 
-RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FuncDeclNode* n)
+RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode* function)
 {
 {
+    unsigned index = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function));
+
     emitOpcode(op_new_func);
     instructions().append(dst->index());
     emitOpcode(op_new_func);
     instructions().append(dst->index());
-    instructions().append(addConstant(n));
+    instructions().append(index);
     return dst;
 }
 
     return dst;
 }
 
@@ -1241,9 +1372,12 @@ RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp)
 
 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
 
 RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n)
 {
+    FunctionBodyNode* function = n->body();
+    unsigned index = m_codeBlock->addFunctionExpr(makeFunction(m_globalData, function));
+
     emitOpcode(op_new_func_exp);
     instructions().append(r0->index());
     emitOpcode(op_new_func_exp);
     instructions().append(r0->index());
-    instructions().append(addConstant(n));
+    instructions().append(index);
     return r0;
 }
 
     return r0;
 }
 
@@ -1252,8 +1386,15 @@ RegisterID* BytecodeGenerator::emitCall(RegisterID* dst, RegisterID* func, Regis
     return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
 }
 
     return emitCall(op_call, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
 }
 
+void BytecodeGenerator::createArgumentsIfNecessary()
+{
+    if (m_codeBlock->usesArguments() && m_codeType == FunctionCode)
+        emitOpcode(op_create_arguments);
+}
+
 RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
 {
 RegisterID* BytecodeGenerator::emitCallEval(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, ArgumentsNode* argumentsNode, unsigned divot, unsigned startOffset, unsigned endOffset)
 {
+    createArgumentsIfNecessary();
     return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
 }
 
     return emitCall(op_call_eval, dst, func, thisRegister, argumentsNode, divot, startOffset, endOffset);
 }
 
@@ -1280,7 +1421,7 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     // Generate code for arguments.
     Vector<RefPtr<RegisterID>, 16> argv;
     argv.append(thisRegister);
     // Generate code for arguments.
     Vector<RefPtr<RegisterID>, 16> argv;
     argv.append(thisRegister);
-    for (ArgumentListNode* n = argumentsNode->m_listNode.get(); n; n = n->m_next.get()) {
+    for (ArgumentListNode* n = argumentsNode->m_listNode; n; n = n->m_next) {
         argv.append(newTemporary());
         // op_call requires the arguments to be a sequential range of registers
         ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
         argv.append(newTemporary());
         // op_call requires the arguments to be a sequential range of registers
         ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
@@ -1327,6 +1468,44 @@ RegisterID* BytecodeGenerator::emitCall(OpcodeID opcodeID, RegisterID* dst, Regi
     return dst;
 }
 
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitLoadVarargs(RegisterID* argCountDst, RegisterID* arguments)
+{
+    ASSERT(argCountDst->index() < arguments->index());
+    emitOpcode(op_load_varargs);
+    instructions().append(argCountDst->index());
+    instructions().append(arguments->index());
+    return argCountDst;
+}
+
+RegisterID* BytecodeGenerator::emitCallVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* argCountRegister, unsigned divot, unsigned startOffset, unsigned endOffset)
+{
+    ASSERT(func->refCount());
+    ASSERT(thisRegister->refCount());
+    ASSERT(dst != func);
+    if (m_shouldEmitProfileHooks) {
+        emitOpcode(op_profile_will_call);
+        instructions().append(func->index());
+        
+#if ENABLE(JIT)
+        m_codeBlock->addFunctionRegisterInfo(instructions().size(), func->index());
+#endif
+    }
+    
+    emitExpressionInfo(divot, startOffset, endOffset);
+    
+    // Emit call.
+    emitOpcode(op_call_varargs);
+    instructions().append(dst->index()); // dst
+    instructions().append(func->index()); // func
+    instructions().append(argCountRegister->index()); // arg count
+    instructions().append(thisRegister->index() + RegisterFile::CallFrameHeaderSize); // initial registerOffset
+    if (m_shouldEmitProfileHooks) {
+        emitOpcode(op_profile_did_call);
+        instructions().append(func->index());
+    }
+    return dst;
+}
+
 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
 {
     if (m_codeBlock->needsFullScopeChain()) {
 RegisterID* BytecodeGenerator::emitReturn(RegisterID* src)
 {
     if (m_codeBlock->needsFullScopeChain()) {
@@ -1365,7 +1544,7 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
     // Generate code for arguments.
     Vector<RefPtr<RegisterID>, 16> argv;
     argv.append(newTemporary()); // reserve space for "this"
     // Generate code for arguments.
     Vector<RefPtr<RegisterID>, 16> argv;
     argv.append(newTemporary()); // reserve space for "this"
-    for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode.get() : 0; n; n = n->m_next.get()) {
+    for (ArgumentListNode* n = argumentsNode ? argumentsNode->m_listNode : 0; n; n = n->m_next) {
         argv.append(newTemporary());
         // op_construct requires the arguments to be a sequential range of registers
         ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
         argv.append(newTemporary());
         // op_construct requires the arguments to be a sequential range of registers
         ASSERT(argv[argv.size() - 1]->index() == argv[argv.size() - 2]->index() + 1);
@@ -1416,6 +1595,23 @@ RegisterID* BytecodeGenerator::emitConstruct(RegisterID* dst, RegisterID* func,
     return dst;
 }
 
     return dst;
 }
 
+RegisterID* BytecodeGenerator::emitStrcat(RegisterID* dst, RegisterID* src, int count)
+{
+    emitOpcode(op_strcat);
+    instructions().append(dst->index());
+    instructions().append(src->index());
+    instructions().append(count);
+
+    return dst;
+}
+
+void BytecodeGenerator::emitToPrimitive(RegisterID* dst, RegisterID* src)
+{
+    emitOpcode(op_to_primitive);
+    instructions().append(dst->index());
+    instructions().append(src->index());
+}
+
 RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
 {
     ASSERT(scope->isTemporary());
 RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
 {
     ASSERT(scope->isTemporary());
@@ -1423,6 +1619,7 @@ RegisterID* BytecodeGenerator::emitPushScope(RegisterID* scope)
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
+    createArgumentsIfNecessary();
 
     return emitUnaryNoDstOp(op_push_scope, scope);
 }
 
     return emitUnaryNoDstOp(op_push_scope, scope);
 }
@@ -1470,8 +1667,17 @@ void BytecodeGenerator::popFinallyContext()
 LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
 {
     // Reclaim free label scopes.
 LabelScope* BytecodeGenerator::breakTarget(const Identifier& name)
 {
     // Reclaim free label scopes.
-    while (m_labelScopes.size() && !m_labelScopes.last().refCount())
+    //
+    // The condition was previously coded as 'm_labelScopes.size() && !m_labelScopes.last().refCount()',
+    // however sometimes this appears to lead to GCC going a little haywire and entering the loop with
+    // size 0, leading to segfaulty badness.  We are yet to identify a valid cause within our code to
+    // cause the GCC codegen to misbehave in this fashion, and as such the following refactoring of the
+    // loop condition is a workaround.
+    while (m_labelScopes.size()) {
+        if  (m_labelScopes.last().refCount())
+            break;
         m_labelScopes.removeLast();
         m_labelScopes.removeLast();
+    }
 
     if (!m_labelScopes.size())
         return 0;
 
     if (!m_labelScopes.size())
         return 0;
@@ -1549,6 +1755,8 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro
         }
 
         if (nNormalScopes) {
         }
 
         if (nNormalScopes) {
+            size_t begin = instructions().size();
+
             // We need to remove a number of dynamic scopes to get to the next
             // finally block
             emitOpcode(op_jmp_scopes);
             // We need to remove a number of dynamic scopes to get to the next
             // finally block
             emitOpcode(op_jmp_scopes);
@@ -1557,25 +1765,21 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro
             // If topScope == bottomScope then there isn't actually a finally block
             // left to emit, so make the jmp_scopes jump directly to the target label
             if (topScope == bottomScope) {
             // If topScope == bottomScope then there isn't actually a finally block
             // left to emit, so make the jmp_scopes jump directly to the target label
             if (topScope == bottomScope) {
-                instructions().append(target->offsetFrom(instructions().size()));
+                instructions().append(target->bind(begin, instructions().size()));
                 return target;
             }
 
             // Otherwise we just use jmp_scopes to pop a group of scopes and go
             // to the next instruction
             RefPtr<Label> nextInsn = newLabel();
                 return target;
             }
 
             // Otherwise we just use jmp_scopes to pop a group of scopes and go
             // to the next instruction
             RefPtr<Label> nextInsn = newLabel();
-            instructions().append(nextInsn->offsetFrom(instructions().size()));
+            instructions().append(nextInsn->bind(begin, instructions().size()));
             emitLabel(nextInsn.get());
         }
 
             emitLabel(nextInsn.get());
         }
 
-        // To get here there must be at least one finally block present
-        do {
-            ASSERT(topScope->isFinallyBlock);
+        while (topScope > bottomScope && topScope->isFinallyBlock) {
             emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
             --topScope;
             emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr);
             --topScope;
-            if (!topScope->isFinallyBlock)
-                break;
-        } while (topScope > bottomScope);
+        }
     }
     return emitJump(target);
 }
     }
     return emitJump(target);
 }
@@ -1593,27 +1797,47 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetSco
     if (m_finallyDepth)
         return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
 
     if (m_finallyDepth)
         return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
 
+    size_t begin = instructions().size();
+
     emitOpcode(op_jmp_scopes);
     instructions().append(scopeDelta);
     emitOpcode(op_jmp_scopes);
     instructions().append(scopeDelta);
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return target;
 }
 
     return target;
 }
 
-RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target)
+RegisterID* BytecodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget)
+{
+    size_t begin = instructions().size();
+
+    emitOpcode(op_get_pnames);
+    instructions().append(dst->index());
+    instructions().append(base->index());
+    instructions().append(i->index());
+    instructions().append(size->index());
+    instructions().append(breakTarget->bind(begin, instructions().size()));
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target)
 {
 {
+    size_t begin = instructions().size();
+
     emitOpcode(op_next_pname);
     instructions().append(dst->index());
     emitOpcode(op_next_pname);
     instructions().append(dst->index());
+    instructions().append(base->index());
+    instructions().append(i->index());
+    instructions().append(size->index());
     instructions().append(iter->index());
     instructions().append(iter->index());
-    instructions().append(target->offsetFrom(instructions().size()));
+    instructions().append(target->bind(begin, instructions().size()));
     return dst;
 }
 
 RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
 {
 #if ENABLE(JIT)
     return dst;
 }
 
 RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
 {
 #if ENABLE(JIT)
-    HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, 0 };
+    HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() };
 #else
 #else
-    HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
+    HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth };
 #endif
 
     m_codeBlock->addExceptionHandler(info);
 #endif
 
     m_codeBlock->addExceptionHandler(info);
@@ -1622,20 +1846,23 @@ RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* star
     return targetRegister;
 }
 
     return targetRegister;
 }
 
-RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValuePtr message)
+RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSValue message)
 {
     emitOpcode(op_new_error);
     instructions().append(dst->index());
     instructions().append(static_cast<int>(type));
 {
     emitOpcode(op_new_error);
     instructions().append(dst->index());
     instructions().append(static_cast<int>(type));
-    instructions().append(addUnexpectedConstant(message));
+    instructions().append(addConstantValue(message)->index());
     return dst;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
 {
     return dst;
 }
 
 PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally)
 {
+    size_t begin = instructions().size();
+
     emitOpcode(op_jsr);
     instructions().append(retAddrDst->index());
     emitOpcode(op_jsr);
     instructions().append(retAddrDst->index());
-    instructions().append(finally->offsetFrom(instructions().size()));
+    instructions().append(finally->bind(begin, instructions().size()));
+    emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it.
     return finally;
 }
 
     return finally;
 }
 
@@ -1645,13 +1872,15 @@ void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc)
     instructions().append(retAddrSrc->index());
 }
 
     instructions().append(retAddrSrc->index());
 }
 
-void BytecodeGenerator::emitPushNewScope(RegisterID* dst, Identifier& property, RegisterID* value)
+void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value)
 {
     ControlFlowContext context;
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
     
 {
     ControlFlowContext context;
     context.isFinallyBlock = false;
     m_scopeContextStack.append(context);
     m_dynamicScopeDepth++;
     
+    createArgumentsIfNecessary();
+
     emitOpcode(op_push_new_scope);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
     emitOpcode(op_push_new_scope);
     instructions().append(dst->index());
     instructions().append(addConstant(property));
@@ -1687,7 +1916,6 @@ static int32_t keyForImmediateSwitch(ExpressionNode* node, int32_t min, int32_t
     ASSERT(node->isNumber());
     double value = static_cast<NumberNode*>(node)->value();
     int32_t key = static_cast<int32_t>(value);
     ASSERT(node->isNumber());
     double value = static_cast<NumberNode*>(node)->value();
     int32_t key = static_cast<int32_t>(value);
-    ASSERT(JSValuePtr::makeInt32Fast(key) && (JSValuePtr::makeInt32Fast(key).getInt32Fast() == value));
     ASSERT(key == value);
     ASSERT(key >= min);
     ASSERT(key <= max);
     ASSERT(key == value);
     ASSERT(key >= min);
     ASSERT(key <= max);
@@ -1703,7 +1931,7 @@ static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32
         // We're emitting this after the clause labels should have been fixed, so 
         // the labels should not be "forward" references
         ASSERT(!labels[i]->isForward());
         // We're emitting this after the clause labels should have been fixed, so 
         // the labels should not be "forward" references
         ASSERT(!labels[i]->isForward());
-        jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); 
+        jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3)); 
     }
 }
 
     }
 }
 
@@ -1729,7 +1957,7 @@ static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32
         // We're emitting this after the clause labels should have been fixed, so 
         // the labels should not be "forward" references
         ASSERT(!labels[i]->isForward());
         // We're emitting this after the clause labels should have been fixed, so 
         // the labels should not be "forward" references
         ASSERT(!labels[i]->isForward());
-        jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); 
+        jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3)); 
     }
 }
 
     }
 }
 
@@ -1743,10 +1971,7 @@ static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t
         ASSERT(nodes[i]->isString());
         UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
         OffsetLocation location;
         ASSERT(nodes[i]->isString());
         UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep();
         OffsetLocation location;
-        location.branchOffset = labels[i]->offsetFrom(switchAddress);
-#if ENABLE(JIT)
-        location.ctiOffset = 0;
-#endif
+        location.branchOffset = labels[i]->bind(switchAddress, switchAddress + 3);
         jumpTable.offsetTable.add(clause, location);
     }
 }
         jumpTable.offsetTable.add(clause, location);
     }
 }
@@ -1757,23 +1982,23 @@ void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, E
     m_switchContextStack.removeLast();
     if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();
     m_switchContextStack.removeLast();
     if (switchInfo.switchType == SwitchInfo::SwitchImmediate) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables();
-        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
 
         SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
 
         SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable();
-        prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);
+        prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
     } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();
     } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) {
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables();
-        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
         
         SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
         
         SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable();
-        prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max);
+        prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max);
     } else {
         ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
     } else {
         ASSERT(switchInfo.switchType == SwitchInfo::SwitchString);
         instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables();
-        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3);
+        instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3);
 
         StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
 
         StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable();
-        prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes);
+        prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes);
     }
 }
 
     }
 }