Revision: 24120
Author:   [email protected]
Date:     Mon Sep 22 13:23:27 2014 UTC
Log:      Make KeyedLoads from a sloppy arguments array use a handler.

Before, a custom stub was installed.

[email protected]

Review URL: https://codereview.chromium.org/546683003
https://code.google.com/p/v8/source/detail?r=24120

Modified:
 /branches/bleeding_edge/src/builtins.cc
 /branches/bleeding_edge/src/builtins.h
 /branches/bleeding_edge/src/code-stubs-hydrogen.cc
 /branches/bleeding_edge/src/code-stubs.cc
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/elements-kind.h
 /branches/bleeding_edge/src/ic/arm/ic-arm.cc
 /branches/bleeding_edge/src/ic/arm64/ic-arm64.cc
 /branches/bleeding_edge/src/ic/handler-compiler.cc
 /branches/bleeding_edge/src/ic/ia32/ic-ia32.cc
 /branches/bleeding_edge/src/ic/ic-compiler.cc
 /branches/bleeding_edge/src/ic/ic.cc
 /branches/bleeding_edge/src/ic/ic.h
 /branches/bleeding_edge/src/ic/mips/ic-mips.cc
 /branches/bleeding_edge/src/ic/x64/ic-x64.cc

=======================================
--- /branches/bleeding_edge/src/builtins.cc     Thu Sep 18 13:28:32 2014 UTC
+++ /branches/bleeding_edge/src/builtins.cc     Mon Sep 22 13:23:27 2014 UTC
@@ -1287,11 +1287,6 @@
 static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
   KeyedLoadIC::GeneratePreMonomorphic(masm);
 }
-
-
-static void Generate_KeyedLoadIC_SloppyArguments(MacroAssembler* masm) {
-  KeyedLoadIC::GenerateSloppyArguments(masm);
-}


 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/builtins.h      Thu Sep 18 13:28:32 2014 UTC
+++ /branches/bleeding_edge/src/builtins.h      Mon Sep 22 13:23:27 2014 UTC
@@ -89,7 +89,6 @@
kNoExtraICState) \ V(KeyedLoadIC_Generic, KEYED_LOAD_IC, GENERIC, kNoExtraICState) \ V(KeyedLoadIC_String, KEYED_LOAD_IC, MEGAMORPHIC, kNoExtraICState) \ - V(KeyedLoadIC_SloppyArguments, KEYED_LOAD_IC, MONOMORPHIC, kNoExtraICState) \ \ V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, StoreIC::kStrictModeState) \ \
=======================================
--- /branches/bleeding_edge/src/code-stubs-hydrogen.cc Tue Sep 16 12:51:33 2014 UTC +++ /branches/bleeding_edge/src/code-stubs-hydrogen.cc Mon Sep 22 13:23:27 2014 UTC
@@ -71,6 +71,8 @@
     MULTIPLE
   };

+  HValue* UnmappedCase(HValue* elements, HValue* key);
+
   HValue* BuildArrayConstructor(ElementsKind kind,
                                 AllocationSiteOverrideMode override_mode,
                                 ArgumentClass argument_class);
@@ -598,6 +600,122 @@


Handle<Code> LoadConstantStub::GenerateCode() { return DoGenerateCode(this); }
+
+
+HValue* CodeStubGraphBuilderBase::UnmappedCase(HValue* elements, HValue* key) {
+  HValue* result;
+  HInstruction* backing_store = Add<HLoadKeyed>(
+      elements, graph()->GetConstant1(), static_cast<HValue*>(NULL),
+      FAST_ELEMENTS, ALLOW_RETURN_HOLE);
+  Add<HCheckMaps>(backing_store, isolate()->factory()->fixed_array_map());
+  HValue* backing_store_length =
+      Add<HLoadNamedField>(backing_store, static_cast<HValue*>(NULL),
+                           HObjectAccess::ForFixedArrayLength());
+  IfBuilder in_unmapped_range(this);
+  in_unmapped_range.If<HCompareNumericAndBranch>(key, backing_store_length,
+                                                 Token::LT);
+  in_unmapped_range.Then();
+  {
+ result = Add<HLoadKeyed>(backing_store, key, static_cast<HValue*>(NULL),
+                             FAST_HOLEY_ELEMENTS, NEVER_RETURN_HOLE);
+  }
+  in_unmapped_range.ElseDeopt("Outside of range");
+  in_unmapped_range.End();
+  return result;
+}
+
+
+template <>
+HValue* CodeStubGraphBuilder<KeyedLoadSloppyArgumentsStub>::BuildCodeStub() {
+  HValue* receiver = GetParameter(LoadDescriptor::kReceiverIndex);
+  HValue* key = GetParameter(LoadDescriptor::kNameIndex);
+
+ // Mapped arguments are actual arguments. Unmapped arguments are values added + // to the arguments object after it was created for the call. Mapped arguments + // are stored in the context at indexes given by elements[key + 2]. Unmapped + // arguments are stored as regular indexed properties in the arguments array, + // held at elements[1]. See NewSloppyArguments() in runtime.cc for a detailed
+  // look at argument object construction.
+  //
+  // The sloppy arguments elements array has a special format:
+  //
+  // 0: context
+  // 1: unmapped arguments array
+  // 2: mapped_index0,
+  // 3: mapped_index1,
+  // ...
+  //
+ // length is 2 + min(number_of_actual_arguments, number_of_formal_arguments).
+  // If key + 2 >= elements.length then attempt to look in the unmapped
+ // arguments array (given by elements[1]) and return the value at key, missing + // to the runtime if the unmapped arguments array is not a fixed array or if
+  // key >= unmapped_arguments_array.length.
+  //
+ // Otherwise, t = elements[key + 2]. If t is the hole, then look up the value + // in the unmapped arguments array, as described above. Otherwise, t is a Smi
+  // index into the context array given at elements[0]. Return the value at
+  // context[t].
+
+  key = AddUncasted<HForceRepresentation>(key, Representation::Smi());
+  IfBuilder positive_smi(this);
+  positive_smi.If<HCompareNumericAndBranch>(key, graph()->GetConstant0(),
+                                            Token::LT);
+  positive_smi.ThenDeopt("key is negative");
+  positive_smi.End();
+
+  HValue* constant_two = Add<HConstant>(2);
+  HValue* elements = AddLoadElements(receiver, static_cast<HValue*>(NULL));
+  HValue* elements_length =
+      Add<HLoadNamedField>(elements, static_cast<HValue*>(NULL),
+                           HObjectAccess::ForFixedArrayLength());
+ HValue* adjusted_length = AddUncasted<HSub>(elements_length, constant_two);
+  IfBuilder in_range(this);
+  in_range.If<HCompareNumericAndBranch>(key, adjusted_length, Token::LT);
+  in_range.Then();
+  {
+    HValue* index = AddUncasted<HAdd>(key, constant_two);
+    HInstruction* mapped_index =
+        Add<HLoadKeyed>(elements, index, static_cast<HValue*>(NULL),
+                        FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
+
+    IfBuilder is_valid(this);
+    is_valid.IfNot<HCompareObjectEqAndBranch>(mapped_index,
+                                              graph()->GetConstantHole());
+    is_valid.Then();
+    {
+      // TODO(mvstanton): I'd like to assert from this point, that if the
+ // mapped_index is not the hole that it is indeed, a smi. An unnecessary
+      // smi check is being emitted.
+      HValue* the_context =
+          Add<HLoadKeyed>(elements, graph()->GetConstant0(),
+                          static_cast<HValue*>(NULL), FAST_ELEMENTS);
+      DCHECK(Context::kHeaderSize == FixedArray::kHeaderSize);
+      HValue* result =
+ Add<HLoadKeyed>(the_context, mapped_index, static_cast<HValue*>(NULL),
+                          FAST_ELEMENTS, ALLOW_RETURN_HOLE);
+      environment()->Push(result);
+    }
+    is_valid.Else();
+    {
+      HValue* result = UnmappedCase(elements, key);
+      environment()->Push(result);
+    }
+    is_valid.End();
+  }
+  in_range.Else();
+  {
+    HValue* result = UnmappedCase(elements, key);
+    environment()->Push(result);
+  }
+  in_range.End();
+
+  return environment()->Pop();
+}
+
+
+Handle<Code> KeyedLoadSloppyArgumentsStub::GenerateCode() {
+  return DoGenerateCode(this);
+}


 void CodeStubGraphBuilderBase::BuildStoreNamedField(
@@ -1092,7 +1210,6 @@
 template <>
 HValue* CodeStubGraphBuilder<StoreGlobalStub>::BuildCodeInitializedStub() {
   StoreGlobalStub* stub = casted_stub();
-  Handle<Object> hole(isolate()->heap()->the_hole_value(), isolate());
   Handle<Object> placeholer_value(Smi::FromInt(0), isolate());
   Handle<PropertyCell> placeholder_cell =
       isolate()->factory()->NewPropertyCell(placeholer_value);
@@ -1124,7 +1241,7 @@
     // property has been deleted and that the store must be handled by the
     // runtime.
     IfBuilder builder(this);
-    HValue* hole_value = Add<HConstant>(hole);
+    HValue* hole_value = graph()->GetConstantHole();
     builder.If<HCompareObjectEqAndBranch>(cell_contents, hole_value);
     builder.Then();
     builder.Deopt("Unexpected cell contents in global store");
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc   Wed Sep 17 12:50:17 2014 UTC
+++ /branches/bleeding_edge/src/code-stubs.cc   Mon Sep 22 13:23:27 2014 UTC
@@ -586,12 +586,14 @@
 void HandlerStub::InitializeDescriptor(CodeStubDescriptor* descriptor) {
   if (kind() == Code::STORE_IC) {
     descriptor->Initialize(FUNCTION_ADDR(StoreIC_MissFromStubFailure));
+  } else if (kind() == Code::KEYED_LOAD_IC) {
+    descriptor->Initialize(FUNCTION_ADDR(KeyedLoadIC_MissFromStubFailure));
   }
 }


 CallInterfaceDescriptor HandlerStub::GetCallInterfaceDescriptor() {
-  if (kind() == Code::LOAD_IC) {
+  if (kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC) {
     return LoadDescriptor(isolate());
   } else {
     DCHECK_EQ(Code::STORE_IC, kind());
=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Thu Sep 18 13:28:32 2014 UTC
+++ /branches/bleeding_edge/src/code-stubs.h    Mon Sep 22 13:23:27 2014 UTC
@@ -82,6 +82,7 @@
   /* IC Handler stubs */                    \
   V(LoadConstant)                           \
   V(LoadField)                              \
+  V(KeyedLoadSloppyArguments)               \
   V(StoreField)                             \
   V(StoreGlobal)                            \
   V(StringLength)
@@ -914,6 +915,20 @@
 };


+class KeyedLoadSloppyArgumentsStub : public HandlerStub {
+ public:
+  explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
+      : HandlerStub(isolate) {}
+
+ protected:
+  virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
+  virtual Code::StubType GetStubType() { return Code::FAST; }
+
+ private:
+  DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
+};
+
+
 class LoadConstantStub : public HandlerStub {
  public:
   LoadConstantStub(Isolate* isolate, int constant_index)
=======================================
--- /branches/bleeding_edge/src/elements-kind.h Mon Aug  4 11:34:54 2014 UTC
+++ /branches/bleeding_edge/src/elements-kind.h Mon Sep 22 13:23:27 2014 UTC
@@ -85,6 +85,11 @@
 inline bool IsDictionaryElementsKind(ElementsKind kind) {
   return kind == DICTIONARY_ELEMENTS;
 }
+
+
+inline bool IsSloppyArgumentsElements(ElementsKind kind) {
+  return kind == SLOPPY_ARGUMENTS_ELEMENTS;
+}


 inline bool IsExternalArrayElementsKind(ElementsKind kind) {
=======================================
--- /branches/bleeding_edge/src/ic/arm/ic-arm.cc Thu Sep 18 13:28:32 2014 UTC +++ /branches/bleeding_edge/src/ic/arm/ic-arm.cc Mon Sep 22 13:23:27 2014 UTC
@@ -367,32 +367,6 @@
__ add(scratch, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
   return MemOperand(backing_store, scratch);
 }
-
-
-void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // The return address is in lr.
-  Register receiver = LoadDescriptor::ReceiverRegister();
-  Register key = LoadDescriptor::NameRegister();
-  DCHECK(receiver.is(r1));
-  DCHECK(key.is(r2));
-
-  Label slow, notin;
-  MemOperand mapped_location = GenerateMappedArgumentsLookup(
-      masm, receiver, key, r0, r3, r4, &notin, &slow);
-  __ ldr(r0, mapped_location);
-  __ Ret();
-  __ bind(&notin);
-  // The unmapped lookup expects that the parameter map is in r0.
-  MemOperand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, key, r0, r3, &slow);
-  __ ldr(r0, unmapped_location);
-  __ LoadRoot(r3, Heap::kTheHoleValueRootIndex);
-  __ cmp(r0, r3);
-  __ b(eq, &slow);
-  __ Ret();
-  __ bind(&slow);
-  GenerateMiss(masm);
-}


 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/ic/arm64/ic-arm64.cc Thu Sep 18 13:28:32 2014 UTC +++ /branches/bleeding_edge/src/ic/arm64/ic-arm64.cc Mon Sep 22 13:23:27 2014 UTC
@@ -368,35 +368,6 @@
__ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister());
   __ TailCallRuntime(Runtime::kGetProperty, 2, 1);
 }
-
-
-void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // The return address is in lr.
-  Register result = x0;
-  Register receiver = LoadDescriptor::ReceiverRegister();
-  Register key = LoadDescriptor::NameRegister();
-  DCHECK(receiver.is(x1));
-  DCHECK(key.is(x2));
-
-  Label miss, unmapped;
-
-  Register map_scratch = x0;
-  MemOperand mapped_location = GenerateMappedArgumentsLookup(
-      masm, receiver, key, map_scratch, x3, x4, &unmapped, &miss);
-  __ Ldr(result, mapped_location);
-  __ Ret();
-
-  __ Bind(&unmapped);
-  // Parameter map is left in map_scratch when a jump on unmapped is done.
-  MemOperand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, key, map_scratch, x3, &miss);
-  __ Ldr(result, unmapped_location);
-  __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss);
-  __ Ret();
-
-  __ Bind(&miss);
-  GenerateMiss(masm);
-}


 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/ic/handler-compiler.cc Thu Sep 18 13:28:32 2014 UTC +++ /branches/bleeding_edge/src/ic/handler-compiler.cc Mon Sep 22 13:23:27 2014 UTC
@@ -390,13 +390,13 @@
       ElementsKind elements_kind = receiver_map->elements_kind();
       if (receiver_map->has_indexed_interceptor()) {
         cached_stub = LoadIndexedInterceptorStub(isolate()).GetCode();
+      } else if (IsSloppyArgumentsElements(elements_kind)) {
+        cached_stub = KeyedLoadSloppyArgumentsStub(isolate()).GetCode();
       } else if (IsFastElementsKind(elements_kind) ||
                  IsExternalArrayElementsKind(elements_kind) ||
                  IsFixedTypedArrayElementsKind(elements_kind)) {
cached_stub = LoadFastElementStub(isolate(), is_js_array, elements_kind)
                           .GetCode();
-      } else if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
-        cached_stub = isolate()->builtins()->KeyedLoadIC_SloppyArguments();
       } else {
         DCHECK(elements_kind == DICTIONARY_ELEMENTS);
         cached_stub = LoadDictionaryElementStub(isolate()).GetCode();
=======================================
--- /branches/bleeding_edge/src/ic/ia32/ic-ia32.cc Thu Sep 18 13:28:32 2014 UTC +++ /branches/bleeding_edge/src/ic/ia32/ic-ia32.cc Mon Sep 22 13:23:27 2014 UTC
@@ -501,32 +501,6 @@
   __ bind(&miss);
   GenerateMiss(masm);
 }
-
-
-void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // The return address is on the stack.
-  Register receiver = LoadDescriptor::ReceiverRegister();
-  Register key = LoadDescriptor::NameRegister();
-  DCHECK(receiver.is(edx));
-  DCHECK(key.is(ecx));
-
-  Label slow, notin;
-  Factory* factory = masm->isolate()->factory();
-  Operand mapped_location = GenerateMappedArgumentsLookup(
-      masm, receiver, key, ebx, eax, &notin, &slow);
-  __ mov(eax, mapped_location);
-  __ Ret();
-  __ bind(&notin);
-  // The unmapped lookup expects that the parameter map is in ebx.
-  Operand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, key, ebx, eax, &slow);
-  __ cmp(unmapped_location, factory->the_hole_value());
-  __ j(equal, &slow);
-  __ mov(eax, unmapped_location);
-  __ Ret();
-  __ bind(&slow);
-  GenerateMiss(masm);
-}


 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/ic/ic-compiler.cc Thu Sep 18 13:28:32 2014 UTC +++ /branches/bleeding_edge/src/ic/ic-compiler.cc Mon Sep 22 13:23:27 2014 UTC
@@ -96,6 +96,8 @@
   Handle<Code> stub;
   if (receiver_map->has_indexed_interceptor()) {
     stub = LoadIndexedInterceptorStub(isolate).GetCode();
+  } else if (receiver_map->has_sloppy_arguments_elements()) {
+    stub = KeyedLoadSloppyArgumentsStub(isolate).GetCode();
   } else if (receiver_map->has_fast_elements() ||
              receiver_map->has_external_array_elements() ||
              receiver_map->has_fixed_typed_array_elements()) {
=======================================
--- /branches/bleeding_edge/src/ic/ic.cc        Fri Sep 19 16:45:59 2014 UTC
+++ /branches/bleeding_edge/src/ic/ic.cc        Mon Sep 22 13:23:27 2014 UTC
@@ -1187,11 +1187,7 @@
       if (state() == UNINITIALIZED) stub = string_stub();
     } else if (object->IsJSObject()) {
       Handle<JSObject> receiver = Handle<JSObject>::cast(object);
-      if (receiver->elements()->map() ==
-          isolate()->heap()->sloppy_arguments_elements_map()) {
-        stub = sloppy_arguments_stub();
-      } else if (!Object::ToSmi(isolate(), key).is_null() &&
-                 (!target().is_identical_to(sloppy_arguments_stub()))) {
+      if (!Object::ToSmi(isolate(), key).is_null()) {
         stub = LoadElementStub(receiver);
       }
     }
=======================================
--- /branches/bleeding_edge/src/ic/ic.h Thu Sep 18 13:28:32 2014 UTC
+++ /branches/bleeding_edge/src/ic/ic.h Mon Sep 22 13:23:27 2014 UTC
@@ -414,7 +414,6 @@
   }
   static void GenerateGeneric(MacroAssembler* masm);
   static void GenerateString(MacroAssembler* masm);
-  static void GenerateSloppyArguments(MacroAssembler* masm);

   // Bit mask to be tested against bit field for the cases when
   // generic stub should go into slow case.
@@ -434,9 +433,6 @@

  private:
   Handle<Code> generic_stub() const { return generic_stub(isolate()); }
-  Handle<Code> sloppy_arguments_stub() {
-    return isolate()->builtins()->KeyedLoadIC_SloppyArguments();
-  }
   Handle<Code> string_stub() {
     return isolate()->builtins()->KeyedLoadIC_String();
   }
=======================================
--- /branches/bleeding_edge/src/ic/mips/ic-mips.cc Thu Sep 18 13:28:32 2014 UTC +++ /branches/bleeding_edge/src/ic/mips/ic-mips.cc Mon Sep 22 13:23:27 2014 UTC
@@ -372,32 +372,6 @@
   __ Addu(scratch, backing_store, scratch);
   return MemOperand(scratch);
 }
-
-
-void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // The return address is in ra.
-  Register receiver = LoadDescriptor::ReceiverRegister();
-  Register key = LoadDescriptor::NameRegister();
-  DCHECK(receiver.is(a1));
-  DCHECK(key.is(a2));
-
-  Label slow, notin;
-  MemOperand mapped_location = GenerateMappedArgumentsLookup(
-      masm, receiver, key, a0, a3, t0, &notin, &slow);
-  __ Ret(USE_DELAY_SLOT);
-  __ lw(v0, mapped_location);
-  __ bind(&notin);
-  // The unmapped lookup expects that the parameter map is in a0.
-  MemOperand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, key, a0, a3, &slow);
-  __ lw(a0, unmapped_location);
-  __ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
-  __ Branch(&slow, eq, a0, Operand(a3));
-  __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a0);
-  __ bind(&slow);
-  GenerateMiss(masm);
-}


 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {
=======================================
--- /branches/bleeding_edge/src/ic/x64/ic-x64.cc Thu Sep 18 13:28:32 2014 UTC +++ /branches/bleeding_edge/src/ic/x64/ic-x64.cc Mon Sep 22 13:23:27 2014 UTC
@@ -720,31 +720,6 @@
   return FieldOperand(backing_store, scratch, times_pointer_size,
                       FixedArray::kHeaderSize);
 }
-
-
-void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // The return address is on the stack.
-  Register receiver = LoadDescriptor::ReceiverRegister();
-  Register key = LoadDescriptor::NameRegister();
-  DCHECK(receiver.is(rdx));
-  DCHECK(key.is(rcx));
-
-  Label slow, notin;
-  Operand mapped_location = GenerateMappedArgumentsLookup(
-      masm, receiver, key, rbx, rax, rdi, &notin, &slow);
-  __ movp(rax, mapped_location);
-  __ Ret();
-  __ bind(&notin);
-  // The unmapped lookup expects that the parameter map is in rbx.
-  Operand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, key, rbx, rax, &slow);
-  __ CompareRoot(unmapped_location, Heap::kTheHoleValueRootIndex);
-  __ j(equal, &slow);
-  __ movp(rax, unmapped_location);
-  __ Ret();
-  __ bind(&slow);
-  GenerateMiss(masm);
-}


 void KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) {

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to