2010-09-25  Oliver Hunt  <oliver@apple.com>

        Reviewed by Cameron Zwarich.

        Avoid constructing arguments object when accessing length and index properties
        https://bugs.webkit.org/show_bug.cgi?id=46572

        Add opcodes to read argument length and properties, and then implement them.
        Much like other lazy opcodes these opcodes take a fast path when the arguments
        object has not been instantiated, and fall back on generic access mechanisms
        if they are acting on an instantiated object.

        3% win on v8-earleyboyer, no change elsewhere.

        * bytecode/CodeBlock.cpp:
        (JSC::CodeBlock::dump):
        * bytecode/Opcode.h:
        * bytecompiler/BytecodeGenerator.cpp:
        (JSC::BytecodeGenerator::emitGetArgumentsLength):
        (JSC::BytecodeGenerator::emitGetArgumentByVal):
        * bytecompiler/BytecodeGenerator.h:
        * bytecompiler/NodesCodegen.cpp:
        (JSC::BracketAccessorNode::emitBytecode):
        (JSC::DotAccessorNode::emitBytecode):
        * interpreter/Interpreter.cpp:
        (JSC::Interpreter::privateExecute):
        * jit/JIT.cpp:
        (JSC::JIT::privateCompileMainPass):
        (JSC::JIT::privateCompileSlowCases):
        * jit/JIT.h:
        * jit/JITOpcodes.cpp:
        (JSC::JIT::emit_op_get_arguments_length):
        (JSC::JIT::emitSlow_op_get_arguments_length):
        (JSC::JIT::emit_op_get_argument_by_val):
        (JSC::JIT::emitSlow_op_get_argument_by_val):
        * jit/JITOpcodes32_64.cpp:
        (JSC::JIT::emit_op_get_arguments_length):
        (JSC::JIT::emitSlow_op_get_arguments_length):
        (JSC::JIT::emit_op_get_argument_by_val):
        (JSC::JIT::emitSlow_op_get_argument_by_val):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@68338 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
index f098ba6..2cc1a3f 100644
--- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp
+++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp
@@ -290,6 +290,12 @@
 
 RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (m_base->isResolveNode() && generator.willResolveToArguments(static_cast<ResolveNode*>(m_base)->identifier())) {
+        RegisterID* property = generator.emitNode(m_subscript);
+        generator.emitExpressionInfo(divot(), startOffset(), endOffset());    
+        return generator.emitGetArgumentByVal(generator.finalDestination(dst), generator.uncheckedRegisterForArguments(), property);
+    }
+
     RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator));
     RegisterID* property = generator.emitNode(m_subscript);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
@@ -300,6 +306,17 @@
 
 RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    if (m_ident == generator.propertyNames().length) {
+        if (!m_base->isResolveNode())
+            goto nonArgumentsPath;
+        ResolveNode* resolveNode = static_cast<ResolveNode*>(m_base);
+        if (!generator.willResolveToArguments(resolveNode->identifier()))
+            goto nonArgumentsPath;
+        generator.emitExpressionInfo(divot(), startOffset(), endOffset());    
+        return generator.emitGetArgumentsLength(generator.finalDestination(dst), generator.uncheckedRegisterForArguments());
+    }
+
+nonArgumentsPath:
     RegisterID* base = generator.emitNode(m_base);
     generator.emitExpressionInfo(divot(), startOffset(), endOffset());
     return generator.emitGetById(generator.finalDestination(dst), base, m_ident);