Revision: 22218
Author:   [email protected]
Date:     Fri Jul  4 16:46:28 2014 UTC
Log:      Version 3.28.13.1 (merged r22168, r22170, r22174)

This corresponds to 3.28.9.1, with r22174 added.

MIPS: KeyedLoadIC should have same register spec as LoadIC.

MIPS: Clean up the global object naming madness.

One of the fast cases in JSObject::MigrateFastToFast() should not be taken if the number of fields did not change.

BUG=chromium:390918
LOG=N
[email protected]

Review URL: https://codereview.chromium.org/368403002
http://code.google.com/p/v8/source/detail?r=22218

Added:
 /trunk/test/mjsunit/regress/regress-crbug-390918.js
Modified:
 /trunk/src/mips/builtins-mips.cc
 /trunk/src/mips/code-stubs-mips.cc
 /trunk/src/mips/debug-mips.cc
 /trunk/src/mips/full-codegen-mips.cc
 /trunk/src/mips/ic-mips.cc
 /trunk/src/mips/lithium-codegen-mips.cc
 /trunk/src/mips/lithium-mips.cc
 /trunk/src/mips/stub-cache-mips.cc
 /trunk/src/objects.cc
 /trunk/src/objects.h
 /trunk/src/version.cc

=======================================
--- /dev/null
+++ /trunk/test/mjsunit/regress/regress-crbug-390918.js Fri Jul 4 16:46:28 2014 UTC
@@ -0,0 +1,18 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+function f(scale) {
+  var arr = {a: 1.1};
+
+  for (var i = 0; i < 2; i++) {
+    arr[2 * scale] = 0;
+  }
+}
+
+f({});
+f({});
+%OptimizeFunctionOnNextCall(f);
+f(1004);
=======================================
--- /trunk/src/mips/builtins-mips.cc    Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/mips/builtins-mips.cc    Fri Jul  4 16:46:28 2014 UTC
@@ -1092,7 +1092,7 @@
   // a1: function
   Label shift_arguments;
__ li(t0, Operand(0, RelocInfo::NONE32)); // Indicate regular JS_FUNCTION.
-  { Label convert_to_object, use_global_receiver, patch_receiver;
+  { Label convert_to_object, use_global_proxy, patch_receiver;
     // Change context eagerly in case we need the global receiver.
     __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset));

@@ -1118,9 +1118,9 @@
     __ JumpIfSmi(a2, &convert_to_object, t2);

     __ LoadRoot(a3, Heap::kUndefinedValueRootIndex);
-    __ Branch(&use_global_receiver, eq, a2, Operand(a3));
+    __ Branch(&use_global_proxy, eq, a2, Operand(a3));
     __ LoadRoot(a3, Heap::kNullValueRootIndex);
-    __ Branch(&use_global_receiver, eq, a2, Operand(a3));
+    __ Branch(&use_global_proxy, eq, a2, Operand(a3));

     STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
     __ GetObjectType(a2, a3, a3);
@@ -1139,16 +1139,17 @@
       __ sra(a0, a0, kSmiTagSize);  // Un-tag.
       // Leave internal frame.
     }
+
     // Restore the function to a1, and the flag to t0.
     __ sll(at, a0, kPointerSizeLog2);
     __ addu(at, sp, at);
     __ lw(a1, MemOperand(at));
-    __ li(t0, Operand(0, RelocInfo::NONE32));
-    __ Branch(&patch_receiver);
+    __ Branch(USE_DELAY_SLOT, &patch_receiver);
+    __ li(t0, Operand(0, RelocInfo::NONE32));  // In delay slot.

-    __ bind(&use_global_receiver);
+    __ bind(&use_global_proxy);
     __ lw(a2, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
-    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
+    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));

     __ bind(&patch_receiver);
     __ sll(at, a0, kPointerSizeLog2);
@@ -1300,7 +1301,7 @@

     // Compute the receiver.
     // Do not transform the receiver for strict mode functions.
-    Label call_to_object, use_global_receiver;
+    Label call_to_object, use_global_proxy;
__ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCompilerHintsOffset));
     __ And(t3, a2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction +
                                  kSmiTagSize)));
@@ -1313,9 +1314,9 @@
     // Compute the receiver in sloppy mode.
     __ JumpIfSmi(a0, &call_to_object);
     __ LoadRoot(a1, Heap::kNullValueRootIndex);
-    __ Branch(&use_global_receiver, eq, a0, Operand(a1));
+    __ Branch(&use_global_proxy, eq, a0, Operand(a1));
     __ LoadRoot(a2, Heap::kUndefinedValueRootIndex);
-    __ Branch(&use_global_receiver, eq, a0, Operand(a2));
+    __ Branch(&use_global_proxy, eq, a0, Operand(a2));

     // Check if the receiver is already a JavaScript object.
     // a0: receiver
@@ -1331,9 +1332,9 @@
__ mov(a0, v0); // Put object in a0 to match other paths to push_receiver.
     __ Branch(&push_receiver);

-    __ bind(&use_global_receiver);
+    __ bind(&use_global_proxy);
     __ lw(a0, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX));
-    __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset));
+    __ lw(a0, FieldMemOperand(a0, GlobalObject::kGlobalProxyOffset));

     // Push the receiver.
     // a0: receiver
=======================================
--- /trunk/src/mips/code-stubs-mips.cc  Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/mips/code-stubs-mips.cc  Fri Jul  4 16:46:28 2014 UTC
@@ -1971,25 +1971,15 @@

 void FunctionPrototypeStub::Generate(MacroAssembler* masm) {
   Label miss;
-  Register receiver;
+  Register receiver = LoadIC::ReceiverRegister();
+  Register name = LoadIC::NameRegister();
+
+  ASSERT(kind() == Code::LOAD_IC ||
+         kind() == Code::KEYED_LOAD_IC);
+
   if (kind() == Code::KEYED_LOAD_IC) {
-    // ----------- S t a t e -------------
-    //  -- ra    : return address
-    //  -- a0    : key
-    //  -- a1    : receiver
-    // -----------------------------------
-    __ Branch(&miss, ne, a0,
+    __ Branch(&miss, ne, name,
         Operand(isolate()->factory()->prototype_string()));
-    receiver = a1;
-  } else {
-    ASSERT(kind() == Code::LOAD_IC);
-    // ----------- S t a t e -------------
-    //  -- a2    : name
-    //  -- ra    : return address
-    //  -- a0    : receiver
-    //  -- sp[0] : receiver
-    // -----------------------------------
-    receiver = a0;
   }

StubCompiler::GenerateLoadFunctionPrototype(masm, receiver, a3, t0, &miss);
=======================================
--- /trunk/src/mips/debug-mips.cc       Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/mips/debug-mips.cc       Fri Jul  4 16:46:28 2014 UTC
@@ -207,9 +207,7 @@

 void DebugCodegen::GenerateKeyedLoadICDebugBreak(MacroAssembler* masm) {
   // Calling convention for keyed IC load (from ic-arm.cc).
-  Register receiver = KeyedLoadIC::ReceiverRegister();
-  Register name = KeyedLoadIC::NameRegister();
-  Generate_DebugBreakCallHelper(masm, receiver.bit() | name.bit(), 0);
+  GenerateLoadICDebugBreak(masm);
 }


=======================================
--- /trunk/src/mips/full-codegen-mips.cc        Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/mips/full-codegen-mips.cc        Fri Jul  4 16:46:28 2014 UTC
@@ -141,7 +141,7 @@
     __ Branch(&ok, ne, a2, Operand(at));

     __ lw(a2, GlobalObjectOperand());
-    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
+    __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));

     __ sw(a2, MemOperand(sp, receiver_offset));

@@ -1871,9 +1871,9 @@
       break;
     case NAMED_PROPERTY:
       if (expr->is_compound()) {
-        // We need the receiver both on the stack and in the accumulator.
-        VisitForAccumulatorValue(property->obj());
-        __ push(result_register());
+        // We need the receiver both on the stack and in the register.
+        VisitForStackValue(property->obj());
+        __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
       } else {
         VisitForStackValue(property->obj());
       }
@@ -1882,9 +1882,9 @@
       // We need the key and receiver on both the stack and in v0 and a1.
       if (expr->is_compound()) {
         VisitForStackValue(property->obj());
-        VisitForAccumulatorValue(property->key());
-        __ lw(a1, MemOperand(sp, 0));
-        __ push(v0);
+        VisitForStackValue(property->key());
+ __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
+        __ lw(LoadIC::NameRegister(), MemOperand(sp, 0));
       } else {
         VisitForStackValue(property->obj());
         VisitForStackValue(property->key());
@@ -2022,6 +2022,9 @@

       Label l_catch, l_try, l_suspend, l_continuation, l_resume;
       Label l_next, l_call;
+      Register load_receiver = LoadIC::ReceiverRegister();
+      Register load_name = LoadIC::NameRegister();
+
       // Initial send value is undefined.
       __ LoadRoot(a0, Heap::kUndefinedValueRootIndex);
       __ Branch(&l_next);
@@ -2030,9 +2033,9 @@
       __ bind(&l_catch);
       __ mov(a0, v0);
       handler_table()->set(expr->index(), Smi::FromInt(l_catch.pos()));
-      __ LoadRoot(a2, Heap::kthrow_stringRootIndex);  // "throw"
-      __ lw(a3, MemOperand(sp, 1 * kPointerSize));    // iter
- __ Push(a2, a3, a0); // "throw", iter, except
+      __ LoadRoot(load_name, Heap::kthrow_stringRootIndex);  // "throw"
+      __ lw(a3, MemOperand(sp, 1 * kPointerSize));           // iter
+ __ Push(load_name, a3, a0); // "throw", iter, except
       __ jmp(&l_call);

       // try { received = %yield result }
@@ -2068,19 +2071,15 @@

       // receiver = iter; f = 'next'; arg = received;
       __ bind(&l_next);
-      Register keyedload_receiver = KeyedLoadIC::ReceiverRegister();
-      Register keyedload_name = KeyedLoadIC::NameRegister();
-      ASSERT(keyedload_receiver.is(a1));
-      ASSERT(keyedload_name.is(a0));

-      __ LoadRoot(a2, Heap::knext_stringRootIndex);    // "next"
-      __ lw(a3, MemOperand(sp, 1 * kPointerSize));     // iter
- __ Push(a2, a3, a0); // "next", iter, received
+      __ LoadRoot(load_name, Heap::knext_stringRootIndex);  // "next"
+      __ lw(a3, MemOperand(sp, 1 * kPointerSize));          // iter
+ __ Push(load_name, a3, a0); // "next", iter, received

       // result = receiver[f](arg);
       __ bind(&l_call);
-      __ lw(keyedload_receiver, MemOperand(sp, kPointerSize));
-      __ lw(keyedload_name, MemOperand(sp, 2 * kPointerSize));
+      __ lw(load_receiver, MemOperand(sp, kPointerSize));
+      __ lw(load_name, MemOperand(sp, 2 * kPointerSize));
       Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
       CallIC(ic, TypeFeedbackId::None());
       __ mov(a0, v0);
@@ -2093,16 +2092,12 @@
       __ Drop(1);  // The function is still on the stack; drop it.

       // if (!result.done) goto l_try;
-      Register load_receiver = LoadIC::ReceiverRegister();
-      Register load_name = LoadIC::NameRegister();
-      ASSERT(load_receiver.is(a0));
-      ASSERT(load_name.is(a2));
+      __ Move(load_receiver, v0);

-      __ mov(load_receiver, v0);
-      __ push(v0);                                          // save result
+      __ push(load_receiver);                               // save result
       __ LoadRoot(load_name, Heap::kdone_stringRootIndex);  // "done"
CallLoadIC(NOT_CONTEXTUAL); // v0=result.done
-      __ mov(load_receiver, v0);
+      __ mov(a0, v0);
       Handle<Code> bool_ic = ToBooleanStub::GetUninitialized(isolate());
       CallIC(bool_ic);
       __ Branch(&l_try, eq, v0, Operand(zero_reg));
@@ -2272,7 +2267,6 @@
 void FullCodeGenerator::EmitNamedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
   Literal* key = prop->key()->AsLiteral();
-  __ mov(LoadIC::ReceiverRegister(), result_register());
   __ li(LoadIC::NameRegister(), Operand(key->value()));
   // Call load IC. It has register arguments receiver and property.
   CallLoadIC(NOT_CONTEXTUAL, prop->PropertyFeedbackId());
@@ -2281,7 +2275,6 @@

 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) {
   SetSourcePosition(prop->position());
-  __ mov(a0, result_register());
   // Call keyed load IC. It has register arguments receiver and key.
   Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   CallIC(ic, prop->PropertyFeedbackId());
@@ -2580,16 +2573,15 @@

   if (key->IsPropertyName()) {
     VisitForAccumulatorValue(expr->obj());
-    ASSERT(a0.is(LoadIC::ReceiverRegister()));
+    __ Move(LoadIC::ReceiverRegister(), v0);
     EmitNamedPropertyLoad(expr);
     PrepareForBailoutForId(expr->LoadId(), TOS_REG);
     context()->Plug(v0);
   } else {
     VisitForStackValue(expr->obj());
     VisitForAccumulatorValue(expr->key());
-    ASSERT(a0.is(KeyedLoadIC::NameRegister()));
-    ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
-    __ pop(KeyedLoadIC::ReceiverRegister());
+    __ Move(LoadIC::NameRegister(), v0);
+    __ pop(LoadIC::ReceiverRegister());
     EmitKeyedPropertyLoad(expr);
     context()->Plug(v0);
   }
@@ -2623,7 +2615,7 @@
   } else {
     // Load the function from the receiver.
     ASSERT(callee->IsProperty());
-    __ lw(v0, MemOperand(sp, 0));
+    __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
     EmitNamedPropertyLoad(callee->AsProperty());
     PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
     // Push the target function under the receiver.
@@ -2641,13 +2633,13 @@
                                                 Expression* key) {
   // Load the key.
   VisitForAccumulatorValue(key);
-  ASSERT(a0.is(KeyedLoadIC::NameRegister()));

   Expression* callee = expr->expression();

   // Load the function from the receiver.
   ASSERT(callee->IsProperty());
-  __ lw(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
+  __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
+  __ Move(LoadIC::NameRegister(), v0);
   EmitKeyedPropertyLoad(callee->AsProperty());
   PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);

@@ -4093,12 +4085,12 @@

   if (expr->is_jsruntime()) {
     // Push the builtins object as the receiver.
-    __ lw(a0, GlobalObjectOperand());
-    __ lw(a0, FieldMemOperand(a0, GlobalObject::kBuiltinsOffset));
-    __ push(a0);
+    Register receiver = LoadIC::ReceiverRegister();
+    __ lw(receiver, GlobalObjectOperand());
+ __ lw(receiver, FieldMemOperand(receiver, GlobalObject::kBuiltinsOffset));
+    __ push(receiver);

     // Load the function from the receiver.
-    ASSERT(a0.is(LoadIC::ReceiverRegister()));
     __ li(LoadIC::NameRegister(), Operand(expr->name()));
     CallLoadIC(NOT_CONTEXTUAL, expr->CallRuntimeFeedbackId());

@@ -4276,16 +4268,15 @@
       __ push(at);
     }
     if (assign_type == NAMED_PROPERTY) {
-      // Put the object both on the stack and in the accumulator.
-      VisitForAccumulatorValue(prop->obj());
-      __ push(v0);
+      // Put the object both on the stack and in the register.
+      VisitForStackValue(prop->obj());
+      __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 0));
       EmitNamedPropertyLoad(prop);
     } else {
       VisitForStackValue(prop->obj());
-      VisitForAccumulatorValue(prop->key());
-      ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
-      __ lw(KeyedLoadIC::ReceiverRegister(), MemOperand(sp, 0));
-      __ push(v0);
+      VisitForStackValue(prop->key());
+      __ lw(LoadIC::ReceiverRegister(), MemOperand(sp, 1 * kPointerSize));
+      __ lw(LoadIC::NameRegister(), MemOperand(sp, 0));
       EmitKeyedPropertyLoad(prop);
     }
   }
=======================================
--- /trunk/src/mips/ic-mips.cc  Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/mips/ic-mips.cc  Fri Jul  4 16:46:28 2014 UTC
@@ -317,18 +317,16 @@


 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
-  // ----------- S t a t e -------------
-  //  -- a2    : name
-  //  -- ra    : return address
-  //  -- a0    : receiver
-  // -----------------------------------
-  ASSERT(a0.is(ReceiverRegister()));
-  ASSERT(a2.is(NameRegister()));
+  // The return address is in lr.
+  Register receiver = ReceiverRegister();
+  Register name = NameRegister();
+  ASSERT(receiver.is(a1));
+  ASSERT(name.is(a2));

   // Probe the stub cache.
   Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC);
   masm->isolate()->stub_cache()->GenerateProbe(
-      masm, flags, a0, a2, a3, t0, t1, t2);
+      masm, flags, receiver, name, a3, t0, t1, t2);

   // Cache miss: Jump to runtime.
   GenerateMiss(masm);
@@ -339,17 +337,17 @@
   // ----------- S t a t e -------------
   //  -- a2    : name
   //  -- lr    : return address
-  //  -- a0    : receiver
+  //  -- a1    : receiver
   // -----------------------------------
-  ASSERT(a0.is(ReceiverRegister()));
+  ASSERT(a1.is(ReceiverRegister()));
   ASSERT(a2.is(NameRegister()));

   Label miss, slow;

-  GenerateNameDictionaryReceiverCheck(masm, a0, a1, a3, t0, &miss);
+  GenerateNameDictionaryReceiverCheck(masm, a1, a0, a3, t0, &miss);

-  // a1: elements
-  GenerateDictionaryLoad(masm, &slow, a1, a2, v0, a3, t0);
+  // a0: elements
+  GenerateDictionaryLoad(masm, &slow, a0, a2, v0, a3, t0);
   __ Ret();

   // Dictionary load failed, go slow (but don't miss).
@@ -367,7 +365,7 @@


 void LoadIC::GenerateMiss(MacroAssembler* masm) {
-  // The return address is on the stack.
+  // The return address is in ra.
   Isolate* isolate = masm->isolate();

   __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0);
@@ -382,7 +380,7 @@


 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
-  // The return address is on the stack.
+  // The return address is in ra.

   __ mov(LoadIC_TempRegister(), ReceiverRegister());
   __ Push(LoadIC_TempRegister(), NameRegister());
@@ -482,27 +480,27 @@


 void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- lr     : return address
-  //  -- a0     : key
-  //  -- a1     : receiver
-  // -----------------------------------
-  ASSERT(a1.is(ReceiverRegister()));
-  ASSERT(a0.is(NameRegister()));
+  // The return address is in ra.
+  Register receiver = ReceiverRegister();
+  Register key = NameRegister();
+  ASSERT(receiver.is(a1));
+  ASSERT(key.is(a2));
+
   Label slow, notin;
   MemOperand mapped_location =
- GenerateMappedArgumentsLookup(masm, a1, a0, a2, a3, t0, &notin, &slow);
+      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 a2.
+  // The unmapped lookup expects that the parameter map is in a0.
   MemOperand unmapped_location =
-      GenerateUnmappedArgumentsLookup(masm, a0, a2, a3, &slow);
-  __ lw(a2, unmapped_location);
+      GenerateUnmappedArgumentsLookup(masm, key, a0, a3, &slow);
+  __ lw(a0, unmapped_location);
   __ LoadRoot(a3, Heap::kTheHoleValueRootIndex);
-  __ Branch(&slow, eq, a2, Operand(a3));
+  __ Branch(&slow, eq, a0, Operand(a3));
   __ Ret(USE_DELAY_SLOT);
-  __ mov(v0, a2);
+  __ mov(v0, a0);
   __ bind(&slow);
   GenerateMiss(masm);
 }
@@ -544,7 +542,7 @@


 void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
-  // The return address is on the stack.
+  // The return address is in ra.
   Isolate* isolate = masm->isolate();

   __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0);
@@ -560,14 +558,12 @@


 // IC register specifications
-const Register LoadIC::ReceiverRegister() { return a0; }
+const Register LoadIC::ReceiverRegister() { return a1; }
 const Register LoadIC::NameRegister() { return a2; }
-const Register KeyedLoadIC::ReceiverRegister() { return a1; }
-const Register KeyedLoadIC::NameRegister() { return a0; }


 void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
-  // The return address is on the stack.
+  // The return address is in ra.

   __ Push(ReceiverRegister(), NameRegister());

@@ -576,17 +572,13 @@


 void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- ra     : return address
-  //  -- a0     : key
-  //  -- a1     : receiver
-  // -----------------------------------
+  // The return address is in ra.
   Label slow, check_name, index_smi, index_name, property_array_property;
   Label probe_dictionary, check_number_dictionary;

   Register key = NameRegister();
   Register receiver = ReceiverRegister();
-  ASSERT(key.is(a0));
+  ASSERT(key.is(a2));
   ASSERT(receiver.is(a1));

   Isolate* isolate = masm->isolate();
@@ -598,15 +590,14 @@
   // where a numeric string is converted to a smi.

   GenerateKeyedLoadReceiverCheck(
-      masm, receiver, a2, a3, Map::kHasIndexedInterceptor, &slow);
+      masm, receiver, a0, a3, Map::kHasIndexedInterceptor, &slow);

   // Check the receiver's map to see if it has fast elements.
-  __ CheckFastElements(a2, a3, &check_number_dictionary);
+  __ CheckFastElements(a0, a3, &check_number_dictionary);

   GenerateFastArrayLoad(
-      masm, receiver, key, t0, a3, a2, v0, NULL, &slow);
-
- __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, a2, a3);
+      masm, receiver, key, a0, a3, t0, v0, NULL, &slow);
+ __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, t0, a3);
   __ Ret();

   __ bind(&check_number_dictionary);
@@ -614,42 +605,41 @@
   __ lw(a3, FieldMemOperand(t0, JSObject::kMapOffset));

   // Check whether the elements is a number dictionary.
-  // a0: key
   // a3: elements map
   // t0: elements
   __ LoadRoot(at, Heap::kHashTableMapRootIndex);
   __ Branch(&slow, ne, a3, Operand(at));
-  __ sra(a2, a0, kSmiTagSize);
-  __ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1);
+  __ sra(a0, key, kSmiTagSize);
+  __ LoadFromNumberDictionary(&slow, t0, key, v0, a0, a3, t1);
   __ Ret();

-  // Slow case, key and receiver still in a0 and a1.
+  // Slow case, key and receiver still in a2 and a1.
   __ bind(&slow);
   __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(),
                       1,
-                      a2,
+                      t0,
                       a3);
   GenerateRuntimeGetProperty(masm);

   __ bind(&check_name);
-  GenerateKeyNameCheck(masm, key, a2, a3, &index_name, &slow);
+  GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow);

   GenerateKeyedLoadReceiverCheck(
-       masm, receiver, a2, a3, Map::kHasNamedInterceptor, &slow);
+       masm, receiver, a0, a3, Map::kHasNamedInterceptor, &slow);


   // If the receiver is a fast-case object, check the keyed lookup
   // cache. Otherwise probe the dictionary.
-  __ lw(a3, FieldMemOperand(a1, JSObject::kPropertiesOffset));
+  __ lw(a3, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
   __ lw(t0, FieldMemOperand(a3, HeapObject::kMapOffset));
   __ LoadRoot(at, Heap::kHashTableMapRootIndex);
   __ Branch(&probe_dictionary, eq, t0, Operand(at));

   // Load the map of the receiver, compute the keyed lookup cache hash
   // based on 32 bits of the map pointer and the name hash.
-  __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
-  __ sra(a3, a2, KeyedLookupCache::kMapHashShift);
-  __ lw(t0, FieldMemOperand(a0, Name::kHashFieldOffset));
+  __ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ sra(a3, a0, KeyedLookupCache::kMapHashShift);
+  __ lw(t0, FieldMemOperand(key, Name::kHashFieldOffset));
   __ sra(at, t0, Name::kHashShift);
   __ xor_(a3, a3, at);
   int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask;
@@ -669,21 +659,19 @@
   for (int i = 0; i < kEntriesPerBucket - 1; i++) {
     Label try_next_entry;
     __ lw(t1, MemOperand(t0, kPointerSize * i * 2));
-    __ Branch(&try_next_entry, ne, a2, Operand(t1));
+    __ Branch(&try_next_entry, ne, a0, Operand(t1));
     __ lw(t1, MemOperand(t0, kPointerSize * (i * 2 + 1)));
-    __ Branch(&hit_on_nth_entry[i], eq, a0, Operand(t1));
+    __ Branch(&hit_on_nth_entry[i], eq, key, Operand(t1));
     __ bind(&try_next_entry);
   }

   __ lw(t1, MemOperand(t0, kPointerSize * (kEntriesPerBucket - 1) * 2));
-  __ Branch(&slow, ne, a2, Operand(t1));
+  __ Branch(&slow, ne, a0, Operand(t1));
__ lw(t1, MemOperand(t0, kPointerSize * ((kEntriesPerBucket - 1) * 2 + 1)));
-  __ Branch(&slow, ne, a0, Operand(t1));
+  __ Branch(&slow, ne, key, Operand(t1));

   // Get field offset.
-  // a0     : key
-  // a1     : receiver
-  // a2     : receiver's map
+  // a0     : receiver's map
   // a3     : lookup cache index
   ExternalReference cache_field_offsets =
       ExternalReference::keyed_lookup_cache_field_offsets(isolate);
@@ -695,7 +683,7 @@
     __ sll(at, a3, kPointerSizeLog2);
     __ addu(at, t0, at);
     __ lw(t1, MemOperand(at, kPointerSize * i));
-    __ lbu(t2, FieldMemOperand(a2, Map::kInObjectPropertiesOffset));
+    __ lbu(t2, FieldMemOperand(a0, Map::kInObjectPropertiesOffset));
     __ Subu(t1, t1, t2);
     __ Branch(&property_array_property, ge, t1, Operand(zero_reg));
     if (i != 0) {
@@ -705,28 +693,28 @@

   // Load in-object property.
   __ bind(&load_in_object_property);
-  __ lbu(t2, FieldMemOperand(a2, Map::kInstanceSizeOffset));
+  __ lbu(t2, FieldMemOperand(a0, Map::kInstanceSizeOffset));
   __ addu(t2, t2, t1);  // Index from start of object.
-  __ Subu(a1, a1, Operand(kHeapObjectTag));  // Remove the heap tag.
+ __ Subu(receiver, receiver, Operand(kHeapObjectTag)); // Remove the heap tag.
   __ sll(at, t2, kPointerSizeLog2);
-  __ addu(at, a1, at);
+  __ addu(at, receiver, at);
   __ lw(v0, MemOperand(at));
__ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
                       1,
-                      a2,
+                      t0,
                       a3);
   __ Ret();

   // Load property array property.
   __ bind(&property_array_property);
-  __ lw(a1, FieldMemOperand(a1, JSObject::kPropertiesOffset));
-  __ Addu(a1, a1, FixedArray::kHeaderSize - kHeapObjectTag);
-  __ sll(t0, t1, kPointerSizeLog2);
-  __ Addu(t0, t0, a1);
-  __ lw(v0, MemOperand(t0));
+  __ lw(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
+  __ Addu(receiver, receiver, FixedArray::kHeaderSize - kHeapObjectTag);
+  __ sll(v0, t1, kPointerSizeLog2);
+  __ Addu(v0, v0, receiver);
+  __ lw(v0, MemOperand(v0));
__ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(),
                       1,
-                      a2,
+                      t0,
                       a3);
   __ Ret();

@@ -734,17 +722,15 @@
   // Do a quick inline probe of the receiver's dictionary, if it
   // exists.
   __ bind(&probe_dictionary);
-  // a1: receiver
-  // a0: key
   // a3: elements
-  __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset));
-  __ lbu(a2, FieldMemOperand(a2, Map::kInstanceTypeOffset));
-  GenerateGlobalInstanceTypeCheck(masm, a2, &slow);
+  __ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset));
+  __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset));
+  GenerateGlobalInstanceTypeCheck(masm, a0, &slow);
   // Load the property to v0.
-  GenerateDictionaryLoad(masm, &slow, a3, a0, v0, a2, t0);
+  GenerateDictionaryLoad(masm, &slow, a3, key, v0, t1, t0);
   __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(),
                       1,
-                      a2,
+                      t0,
                       a3);
   __ Ret();

@@ -756,7 +742,7 @@


 void KeyedLoadIC::GenerateString(MacroAssembler* masm) {
-  // Return address is on the stack.
+  // Return address is in ra.
   Label miss;

   Register receiver = ReceiverRegister();
@@ -1071,13 +1057,13 @@


 void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
-  // Return address is on the stack.
+  // Return address is in ra.
   Label slow;

   Register receiver = ReceiverRegister();
   Register key = NameRegister();
-  Register scratch1 = a2;
-  Register scratch2 = a3;
+  Register scratch1 = a3;
+  Register scratch2 = t0;
   ASSERT(!scratch1.is(receiver) && !scratch1.is(key));
   ASSERT(!scratch2.is(receiver) && !scratch2.is(key));

=======================================
--- /trunk/src/mips/lithium-codegen-mips.cc     Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/mips/lithium-codegen-mips.cc     Fri Jul  4 16:46:28 2014 UTC
@@ -152,7 +152,7 @@
       __ Branch(&ok, ne, a2, Operand(at));

       __ lw(a2, GlobalObjectOperand());
-      __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalReceiverOffset));
+      __ lw(a2, FieldMemOperand(a2, GlobalObject::kGlobalProxyOffset));

       __ sw(a2, MemOperand(sp, receiver_offset));

@@ -3327,8 +3327,8 @@

 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) {
   ASSERT(ToRegister(instr->context()).is(cp));
-  ASSERT(ToRegister(instr->object()).is(KeyedLoadIC::ReceiverRegister()));
-  ASSERT(ToRegister(instr->key()).is(KeyedLoadIC::NameRegister()));
+  ASSERT(ToRegister(instr->object()).is(LoadIC::ReceiverRegister()));
+  ASSERT(ToRegister(instr->key()).is(LoadIC::NameRegister()));

   Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize();
   CallCode(ic, RelocInfo::CODE_TARGET, instr);
@@ -3425,7 +3425,7 @@
   __ lw(result,
         ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
   __ lw(result,
-        FieldMemOperand(result, GlobalObject::kGlobalReceiverOffset));
+        FieldMemOperand(result, GlobalObject::kGlobalProxyOffset));

   if (result.is(receiver)) {
     __ bind(&result_in_receiver);
=======================================
--- /trunk/src/mips/lithium-mips.cc     Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/mips/lithium-mips.cc     Fri Jul  4 16:46:28 2014 UTC
@@ -2145,8 +2145,8 @@

 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) {
   LOperand* context = UseFixed(instr->context(), cp);
- LOperand* object = UseFixed(instr->object(), KeyedLoadIC::ReceiverRegister());
-  LOperand* key = UseFixed(instr->key(), KeyedLoadIC::NameRegister());
+  LOperand* object = UseFixed(instr->object(), LoadIC::ReceiverRegister());
+  LOperand* key = UseFixed(instr->key(), LoadIC::NameRegister());

   LInstruction* result =
       DefineFixed(new(zone()) LLoadKeyedGeneric(context, object, key), v0);
=======================================
--- /trunk/src/mips/stub-cache-mips.cc  Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/mips/stub-cache-mips.cc  Fri Jul  4 16:46:28 2014 UTC
@@ -1195,8 +1195,7 @@
       if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
         // Swap in the global receiver.
         __ lw(receiver,
-               FieldMemOperand(
-                   receiver, JSGlobalObject::kGlobalReceiverOffset));
+ FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
       }
       __ Push(receiver, value());
       ParameterCount actual(1);
@@ -1256,16 +1255,16 @@
   // receiver, name, scratch1, scratch2, scratch3, scratch4.
   Register receiver = LoadIC::ReceiverRegister();
   Register name = LoadIC::NameRegister();
-  static Register registers[] = { receiver, name, a3, a1, t0, t1 };
+  static Register registers[] = { receiver, name, a3, a0, t0, t1 };
   return registers;
 }


 Register* KeyedLoadStubCompiler::registers() {
   // receiver, name, scratch1, scratch2, scratch3, scratch4.
-  Register receiver = KeyedLoadIC::ReceiverRegister();
-  Register name = KeyedLoadIC::NameRegister();
-  static Register registers[] = { receiver, name, a2, a3, t0, t1 };
+  Register receiver = LoadIC::ReceiverRegister();
+  Register name = LoadIC::NameRegister();
+  static Register registers[] = { receiver, name, a3, a0, t0, t1 };
   return registers;
 }

@@ -1310,8 +1309,7 @@
       if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
         // Swap in the global receiver.
         __ lw(receiver,
-                FieldMemOperand(
-                    receiver, JSGlobalObject::kGlobalReceiverOffset));
+ FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
       }
       __ push(receiver);
       ParameterCount actual(0);
@@ -1466,45 +1464,30 @@

 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
     MacroAssembler* masm) {
-  // ---------- S t a t e --------------
-  //  -- ra     : return address
-  //  -- a0     : key
-  //  -- a1     : receiver
-  // -----------------------------------
-  ASSERT(a1.is(KeyedLoadIC::ReceiverRegister()));
-  ASSERT(a0.is(KeyedLoadIC::NameRegister()));
+  // The return address is in ra.
   Label slow, miss;

-  Register key = a0;
-  Register receiver = a1;
+  Register key = LoadIC::NameRegister();
+  Register receiver = LoadIC::ReceiverRegister();
+  ASSERT(receiver.is(a1));
+  ASSERT(key.is(a2));

-  __ JumpIfNotSmi(key, &miss);
+  __ UntagAndJumpIfNotSmi(t2, key, &miss);
   __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset));
-  __ sra(a2, a0, kSmiTagSize);
-  __ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1);
+  __ LoadFromNumberDictionary(&slow, t0, key, v0, t2, a3, t1);
   __ Ret();

-  // Slow case, key and receiver still in a0 and a1.
+  // Slow case, key and receiver still unmodified.
   __ bind(&slow);
   __ IncrementCounter(
       masm->isolate()->counters()->keyed_load_external_array_slow(),
       1, a2, a3);
-  // Entry registers are intact.
-  // ---------- S t a t e --------------
-  //  -- ra     : return address
-  //  -- a0     : key
-  //  -- a1     : receiver
-  // -----------------------------------
+
   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);

   // Miss case, call the runtime.
   __ bind(&miss);

-  // ---------- S t a t e --------------
-  //  -- ra     : return address
-  //  -- a0     : key
-  //  -- a1     : receiver
-  // -----------------------------------
   TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
 }

=======================================
--- /trunk/src/objects.cc       Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/objects.cc       Fri Jul  4 16:46:28 2014 UTC
@@ -2062,14 +2062,13 @@
 }


-bool Map::InstancesNeedRewriting(Map* target,
-                                 int target_number_of_fields,
-                                 int target_inobject,
-                                 int target_unused) {
+bool Map::InstancesNeedRewriting(Map* target, int target_number_of_fields,
+                                 int target_inobject, int target_unused,
+                                 int* old_number_of_fields) {
   // If fields were added (or removed), rewrite the instance.
-  int number_of_fields = NumberOfFields();
-  ASSERT(target_number_of_fields >= number_of_fields);
-  if (target_number_of_fields != number_of_fields) return true;
+  *old_number_of_fields = NumberOfFields();
+  ASSERT(target_number_of_fields >= *old_number_of_fields);
+  if (target_number_of_fields != *old_number_of_fields) return true;

   // If smi descriptors were replaced by double descriptors, rewrite.
   DescriptorArray* old_desc = instance_descriptors();
@@ -2147,14 +2146,15 @@
void JSObject::MigrateFastToFast(Handle<JSObject> object, Handle<Map> new_map) {
   Isolate* isolate = object->GetIsolate();
   Handle<Map> old_map(object->map());
+  int old_number_of_fields;
   int number_of_fields = new_map->NumberOfFields();
   int inobject = new_map->inobject_properties();
   int unused = new_map->unused_property_fields();

// Nothing to do if no functions were converted to fields and no smis were
   // converted to doubles.
-  if (!old_map->InstancesNeedRewriting(
-          *new_map, number_of_fields, inobject, unused)) {
+ if (!old_map->InstancesNeedRewriting(*new_map, number_of_fields, inobject,
+                                       unused, &old_number_of_fields)) {
     object->synchronized_set_map(*new_map);
     return;
   }
@@ -2163,7 +2163,9 @@
   int external = total_size - inobject;

   if ((old_map->unused_property_fields() == 0) &&
+      (number_of_fields != old_number_of_fields) &&
       (new_map->GetBackPointer() == *old_map)) {
+    ASSERT(number_of_fields == old_number_of_fields + 1);
// This migration is a transition from a map that has run out out property
     // space. Therefore it could be done by extending the backing store.
     Handle<FixedArray> old_storage = handle(object->properties(), isolate);
=======================================
--- /trunk/src/objects.h        Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/objects.h        Fri Jul  4 16:46:28 2014 UTC
@@ -6285,10 +6285,9 @@
   int NumberOfFields();

   // TODO(ishell): candidate with JSObject::MigrateToMap().
-  bool InstancesNeedRewriting(Map* target,
-                              int target_number_of_fields,
-                              int target_inobject,
-                              int target_unused);
+  bool InstancesNeedRewriting(Map* target, int target_number_of_fields,
+                              int target_inobject, int target_unused,
+                              int* old_number_of_fields);
   // TODO(ishell): moveit!
   static Handle<Map> GeneralizeAllFieldRepresentations(Handle<Map> map);
   MUST_USE_RESULT static Handle<HeapType> GeneralizeFieldType(
=======================================
--- /trunk/src/version.cc       Fri Jul  4 16:39:51 2014 UTC
+++ /trunk/src/version.cc       Fri Jul  4 16:46:28 2014 UTC
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     28
 #define BUILD_NUMBER      13
-#define PATCH_LEVEL       0
+#define PATCH_LEVEL       1
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0

--
--
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