Reviewers: Yang,

Description:
Add missing lazy deopt point for the TransitionElementsKind instruction.

[email protected]
BUG=357105
TEST=test/mjsunit/regress/regress-357105.js
LOG=N

Please review this at https://codereview.chromium.org/216963002/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+58, -30 lines):
  M src/arm/lithium-arm.cc
  M src/arm/lithium-codegen-arm.cc
  M src/arm64/lithium-arm64.h
  M src/arm64/lithium-arm64.cc
  M src/arm64/lithium-codegen-arm64.cc
  M src/ia32/lithium-codegen-ia32.cc
  M src/ia32/lithium-ia32.cc
  M src/mips/lithium-codegen-mips.cc
  M src/mips/lithium-mips.cc
  M src/x64/lithium-codegen-x64.cc
  M src/x64/lithium-x64.cc
  A test/mjsunit/regress/regress-357105.js


Index: src/arm/lithium-arm.cc
diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
index 55705b8073cfd0a8e3f91b8d7aa1beca58b1b978..c280999ca2b0849d7710fa89814d9ae472de7aa4 100644
--- a/src/arm/lithium-arm.cc
+++ b/src/arm/lithium-arm.cc
@@ -2225,17 +2225,18 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {

 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
-  LOperand* object = UseRegister(instr->object());
   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
+    LOperand* object = UseRegister(instr->object());
     LOperand* new_map_reg = TempRegister();
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, NULL, new_map_reg);
     return result;
   } else {
+    LOperand* object = UseFixed(instr->object(), r0);
     LOperand* context = UseFixed(instr->context(), cp);
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, context, NULL);
-    return AssignPointerMap(result);
+    return MarkAsCall(result, instr);
   }
 }

Index: src/arm/lithium-codegen-arm.cc
diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
index 7152ba21cc2af690406d1d209eba6087c6f53dce..9cf94eea8470384be29a04335fef80dceb0ba50e 100644
--- a/src/arm/lithium-codegen-arm.cc
+++ b/src/arm/lithium-codegen-arm.cc
@@ -4381,15 +4381,15 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
                         scratch, GetLinkRegisterState(), kDontSaveFPRegs);
   } else {
     ASSERT(ToRegister(instr->context()).is(cp));
+    ASSERT(object_reg.is(r0));
     PushSafepointRegistersScope scope(
         this, Safepoint::kWithRegistersAndDoubles);
-    __ Move(r0, object_reg);
     __ Move(r1, to_map);
     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
     TransitionElementsKindStub stub(from_kind, to_kind, is_js_array);
     __ CallStub(&stub);
     RecordSafepointWithRegistersAndDoubles(
-        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
   }
   __ bind(&not_applicable);
 }
Index: src/arm64/lithium-arm64.cc
diff --git a/src/arm64/lithium-arm64.cc b/src/arm64/lithium-arm64.cc
index 60bf51ebbdc7d33170faff92dcf106d777a1f7c4..6dccc5ffaa86218b80176f94843d5d8c3cd63fc9 100644
--- a/src/arm64/lithium-arm64.cc
+++ b/src/arm64/lithium-arm64.cc
@@ -2365,17 +2365,18 @@ LInstruction* LChunkBuilder::DoToFastProperties(HToFastProperties* instr) {

 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
-  LOperand* object = UseRegister(instr->object());
   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
+    LOperand* object = UseRegister(instr->object());
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, NULL,
TempRegister(), TempRegister());
     return result;
   } else {
+    LOperand* object = UseFixed(instr->object(), x0);
     LOperand* context = UseFixed(instr->context(), cp);
     LTransitionElementsKind* result =
- new(zone()) LTransitionElementsKind(object, context, TempRegister());
-    return AssignPointerMap(result);
+        new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
+    return MarkAsCall(result, instr);
   }
 }

Index: src/arm64/lithium-arm64.h
diff --git a/src/arm64/lithium-arm64.h b/src/arm64/lithium-arm64.h
index da3c5f17b5a7ed757882b4843923e7afa817a97a..fcb15526048f0d273dd746ec2ae1a8756019824c 100644
--- a/src/arm64/lithium-arm64.h
+++ b/src/arm64/lithium-arm64.h
@@ -2778,7 +2778,7 @@ class LTransitionElementsKind V8_FINAL : public LTemplateInstruction<0, 2, 2> {
   LTransitionElementsKind(LOperand* object,
                           LOperand* context,
                           LOperand* temp1,
-                          LOperand* temp2 = NULL) {
+                          LOperand* temp2) {
     inputs_[0] = object;
     inputs_[1] = context;
     temps_[0] = temp1;
Index: src/arm64/lithium-codegen-arm64.cc
diff --git a/src/arm64/lithium-codegen-arm64.cc b/src/arm64/lithium-codegen-arm64.cc index cd931e934c7c8b52fc5633d997b563368ea03828..abae911512cace247fdfd25a3f267048bc21e760 100644
--- a/src/arm64/lithium-codegen-arm64.cc
+++ b/src/arm64/lithium-codegen-arm64.cc
@@ -5659,7 +5659,6 @@ void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) {

 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
   Register object = ToRegister(instr->object());
-  Register temp1 = ToRegister(instr->temp1());

   Handle<Map> from_map = instr->original_map();
   Handle<Map> to_map = instr->transitioned_map();
@@ -5667,26 +5666,34 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
   ElementsKind to_kind = instr->to_kind();

   Label not_applicable;
-  __ CheckMap(object, temp1, from_map, &not_applicable, DONT_DO_SMI_CHECK);

   if (IsSimpleMapChangeTransition(from_kind, to_kind)) {
+    Register temp1 = ToRegister(instr->temp1());
     Register new_map = ToRegister(instr->temp2());
+ __ CheckMap(object, temp1, from_map, &not_applicable, DONT_DO_SMI_CHECK);
     __ Mov(new_map, Operand(to_map));
     __ Str(new_map, FieldMemOperand(object, HeapObject::kMapOffset));
     // Write barrier.
     __ RecordWriteField(object, HeapObject::kMapOffset, new_map, temp1,
                         GetLinkRegisterState(), kDontSaveFPRegs);
   } else {
+    {
+      UseScratchRegisterScope temps(masm());
+ // Use the temp register only in a restricted scope - the codegen checks
+      // that we do not use any register across a call.
+      __ CheckMap(object, temps.AcquireX(), from_map, &not_applicable,
+                  DONT_DO_SMI_CHECK);
+    }
+    ASSERT(object.is(x0));
     ASSERT(ToRegister(instr->context()).is(cp));
     PushSafepointRegistersScope scope(
         this, Safepoint::kWithRegistersAndDoubles);
-    __ Mov(x0, object);
     __ Mov(x1, Operand(to_map));
     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
     TransitionElementsKindStub stub(from_kind, to_kind, is_js_array);
     __ CallStub(&stub);
     RecordSafepointWithRegistersAndDoubles(
-        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
   }
   __ Bind(&not_applicable);
 }
Index: src/ia32/lithium-codegen-ia32.cc
diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 0dbe3da13d3f1b4f59bfd2b1f31a1fbaf84c6eaa..b3c06d6778957c9152a6fe2bfa42737faeb5f419 100644
--- a/src/ia32/lithium-codegen-ia32.cc
+++ b/src/ia32/lithium-codegen-ia32.cc
@@ -4736,16 +4736,14 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
                          kDontSaveFPRegs);
   } else {
     ASSERT(ToRegister(instr->context()).is(esi));
+    ASSERT(object_reg.is(eax));
     PushSafepointRegistersScope scope(this);
-    if (!object_reg.is(eax)) {
-      __ mov(eax, object_reg);
-    }
     __ mov(ebx, to_map);
     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
     TransitionElementsKindStub stub(from_kind, to_kind, is_js_array);
     __ CallStub(&stub);
-    RecordSafepointWithRegisters(
-        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+    RecordSafepointWithLazyDeopt(instr,
+        RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
   }
   __ bind(&not_applicable);
 }
Index: src/ia32/lithium-ia32.cc
diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
index 696c6be6e8159cd8ba3427dab2f8eb6e0717400c..8fa6dbdcaed689256948f7c21e6a4785100c082d 100644
--- a/src/ia32/lithium-ia32.cc
+++ b/src/ia32/lithium-ia32.cc
@@ -2345,7 +2345,6 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {

 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
-  LOperand* object = UseRegister(instr->object());
   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
     LOperand* object = UseRegister(instr->object());
     LOperand* new_map_reg = TempRegister();
@@ -2355,10 +2354,11 @@ LInstruction* LChunkBuilder::DoTransitionElementsKind(
                                             new_map_reg, temp_reg);
     return result;
   } else {
+    LOperand* object = UseFixed(instr->object(), eax);
     LOperand* context = UseFixed(instr->context(), esi);
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
-    return AssignPointerMap(result);
+    return MarkAsCall(result, instr);
   }
 }

Index: src/mips/lithium-codegen-mips.cc
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 970a1bfc25c197ad78e95442408aa05a59cebd15..e6f52d84b707ef82d3385eddea892525039b744d 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -4401,16 +4401,16 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
     __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
                         scratch, GetRAState(), kDontSaveFPRegs);
   } else {
+    ASSERT(object_reg.is(a0));
     ASSERT(ToRegister(instr->context()).is(cp));
     PushSafepointRegistersScope scope(
         this, Safepoint::kWithRegistersAndDoubles);
-    __ mov(a0, object_reg);
     __ li(a1, Operand(to_map));
     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
     TransitionElementsKindStub stub(from_kind, to_kind, is_js_array);
     __ CallStub(&stub);
     RecordSafepointWithRegistersAndDoubles(
-        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+        instr->pointer_map(), 0, Safepoint::kLazyDeopt);
   }
   __ bind(&not_applicable);
 }
Index: src/mips/lithium-mips.cc
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 752f67673d76841120c4a2b4be96fbef29ec84cd..1ff8915f515bbe083112adf622ddf926b4c448f2 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -2178,17 +2178,18 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {

 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
-  LOperand* object = UseRegister(instr->object());
   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
+    LOperand* object = UseRegister(instr->object());
     LOperand* new_map_reg = TempRegister();
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, NULL, new_map_reg);
     return result;
   } else {
+    LOperand* object = UseFixed(instr->object(), a0);
     LOperand* context = UseFixed(instr->context(), cp);
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, context, NULL);
-    return AssignPointerMap(result);
+    return MarkAsCall(result, instr);
   }
 }

Index: src/x64/lithium-codegen-x64.cc
diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
index cc9b21b79f671ff017326202cbdba499af56e80f..849e2d4ecaa6bf131dc13a938dba82b667e1dd81 100644
--- a/src/x64/lithium-codegen-x64.cc
+++ b/src/x64/lithium-codegen-x64.cc
@@ -4318,17 +4318,14 @@ void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
     __ RecordWriteField(object_reg, HeapObject::kMapOffset, new_map_reg,
                         ToRegister(instr->temp()), kDontSaveFPRegs);
   } else {
+    ASSERT(object_reg.is(rax));
     ASSERT(ToRegister(instr->context()).is(rsi));
     PushSafepointRegistersScope scope(this);
-    if (!object_reg.is(rax)) {
-      __ movp(rax, object_reg);
-    }
     __ Move(rbx, to_map);
     bool is_js_array = from_map->instance_type() == JS_ARRAY_TYPE;
     TransitionElementsKindStub stub(from_kind, to_kind, is_js_array);
     __ CallStub(&stub);
-    RecordSafepointWithRegisters(
-        instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
+ RecordSafepointWithLazyDeopt(instr, RECORD_SAFEPOINT_WITH_REGISTERS, 0);
   }
   __ bind(&not_applicable);
 }
Index: src/x64/lithium-x64.cc
diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
index 8c4f24e8fb465680beaf3d0a1bd1deb102cb676f..0dba33dc91ea83959c8859ebe3d3a3b5a09adae8 100644
--- a/src/x64/lithium-x64.cc
+++ b/src/x64/lithium-x64.cc
@@ -2243,7 +2243,6 @@ LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) {

 LInstruction* LChunkBuilder::DoTransitionElementsKind(
     HTransitionElementsKind* instr) {
-  LOperand* object = UseRegister(instr->object());
   if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) {
     LOperand* object = UseRegister(instr->object());
     LOperand* new_map_reg = TempRegister();
@@ -2252,10 +2251,11 @@ LInstruction* LChunkBuilder::DoTransitionElementsKind(
         object, NULL, new_map_reg, temp_reg);
     return result;
   } else {
+    LOperand* object = UseFixed(instr->object(), rax);
     LOperand* context = UseFixed(instr->context(), rsi);
     LTransitionElementsKind* result =
         new(zone()) LTransitionElementsKind(object, context, NULL, NULL);
-    return AssignPointerMap(result);
+    return MarkAsCall(result, instr);
   }
 }

Index: test/mjsunit/regress/regress-357105.js
diff --git a/test/mjsunit/regress/regress-357105.js b/test/mjsunit/regress/regress-357105.js
new file mode 100644
index 0000000000000000000000000000000000000000..d3eefd0f1b6a4616e5b57a2e79555619d76993bf
--- /dev/null
+++ b/test/mjsunit/regress/regress-357105.js
@@ -0,0 +1,23 @@
+// 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 --expose-gc
+
+var global = { };
+
+function do_nothing() { }
+
+function f(opt_gc) {
+  var x = new Array(3);
+  x[0] = 10;
+  opt_gc();
+  global[1] = 15.5;
+  return x;
+}
+
+gc();
+global = f(gc);
+global = f(do_nothing);
+%OptimizeFunctionOnNextCall(f);
+global = f(do_nothing);


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