Revision: 4761
Author: [email protected]
Date: Tue Jun  1 01:00:12 2010
Log: Merge 4759:4760 from bleeding_edge to experimental/isolates.
Review URL: http://codereview.chromium.org/2453001
http://code.google.com/p/v8/source/detail?r=4761

Modified:
 /branches/experimental/isolates/src/arm/ic-arm.cc
 /branches/experimental/isolates/src/ia32/ic-ia32.cc
 /branches/experimental/isolates/src/x64/codegen-x64.cc
 /branches/experimental/isolates/src/x64/debug-x64.cc
 /branches/experimental/isolates/src/x64/full-codegen-x64.cc
 /branches/experimental/isolates/src/x64/ic-x64.cc
 /branches/experimental/isolates/src/x64/stub-cache-x64.cc
 /branches/experimental/isolates/src/x64/virtual-frame-x64.cc
 /branches/experimental/isolates/test/mjsunit/delete.js

=======================================
--- /branches/experimental/isolates/src/arm/ic-arm.cc Mon May 31 21:48:19 2010 +++ /branches/experimental/isolates/src/arm/ic-arm.cc Tue Jun 1 01:00:12 2010
@@ -56,15 +56,14 @@
   //
   // t0 - used to hold the property dictionary.
   //
-  // t1 - initially the receiver
-  //    - used for the index into the property dictionary
+  // t1 - initially the receiver.
   //    - holds the result on exit.
   //
   // r3 - used as temporary and to hold the capacity of the property
   //      dictionary.
   //
-  // r2 - holds the name of the property and is unchanged.
-  // r4 - used as temporary.
+  // r2 - initially holds the name of the property and is unchanged.
+  // r4 - used to hold the index into the property dictionary.

   Label done;

@@ -542,7 +541,7 @@
   __ CheckAccessGlobalProxy(r0, r1, &miss);
   __ b(&probe);

-  // Cache miss: Restore receiver from stack and jump to runtime.
+  // Cache miss: Jump to runtime.
   __ bind(&miss);
   GenerateMiss(masm);
 }
=======================================
--- /branches/experimental/isolates/src/ia32/ic-ia32.cc Mon May 31 21:48:19 2010 +++ /branches/experimental/isolates/src/ia32/ic-ia32.cc Tue Jun 1 01:00:12 2010
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2010 the V8 project authors. All rights reserved.
 // Redistribution and use in source and binary forms, with or without
 // modification, are permitted provided that the following conditions are
 // met:
@@ -1322,7 +1322,7 @@
   __ CheckAccessGlobalProxy(eax, edx, &miss);
   __ jmp(&probe);

-  // Cache miss: Restore receiver from stack and jump to runtime.
+  // Cache miss: Jump to runtime.
   __ bind(&miss);
   GenerateMiss(masm);
 }
=======================================
--- /branches/experimental/isolates/src/x64/codegen-x64.cc Mon May 31 21:48:19 2010 +++ /branches/experimental/isolates/src/x64/codegen-x64.cc Tue Jun 1 01:00:12 2010
@@ -794,6 +794,7 @@
   // Load applicand.apply onto the stack. This will usually
   // give us a megamorphic load site. Not super, but it works.
   Load(applicand);
+  frame()->Dup();
   Handle<String> name = Factory::LookupAsciiSymbol("apply");
   frame()->Push(name);
   Result answer = frame()->CallLoadIC(RelocInfo::CODE_TARGET);
@@ -5791,8 +5792,6 @@
   // property case was inlined.  Ensure that there is not a test rax
   // instruction here.
   masm_->nop();
-  // Discard the global object. The result is in answer.
-  frame_->Drop();
   return answer;
 }

@@ -6740,7 +6739,9 @@


 void DeferredReferenceGetNamedValue::Generate() {
-  __ push(receiver_);
+  if (!receiver_.is(rax)) {
+    __ movq(rax, receiver_);
+  }
   __ Move(rcx, name_);
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   __ Call(ic, RelocInfo::CODE_TARGET);
@@ -6757,7 +6758,6 @@
   __ IncrementCounter(&Counters::named_load_inline_miss, 1);

   if (!dst_.is(rax)) __ movq(dst_, rax);
-  __ pop(receiver_);
 }


@@ -7418,9 +7418,8 @@

     __ IncrementCounter(&Counters::named_load_inline, 1);
     deferred->BindExit();
-    frame()->Push(&receiver);
-  }
-  ASSERT(frame()->height() == original_height);
+  }
+  ASSERT(frame()->height() == original_height - 1);
   return result;
 }

@@ -7569,10 +7568,13 @@
       Variable* var = expression_->AsVariableProxy()->AsVariable();
       bool is_global = var != NULL;
       ASSERT(!is_global || var->is_global());
+      if (persist_after_get_) {
+        cgen_->frame()->Dup();
+      }
       Result result = cgen_->EmitNamedLoad(GetName(), is_global);
       cgen_->frame()->Push(&result);
       if (!persist_after_get_) {
-        cgen_->UnloadReference(this);
+        set_unloaded();
       }
       break;
     }
=======================================
--- /branches/experimental/isolates/src/x64/debug-x64.cc Thu May 20 08:09:21 2010 +++ /branches/experimental/isolates/src/x64/debug-x64.cc Tue Jun 1 01:00:12 2010
@@ -144,9 +144,10 @@
 void Debug::GenerateLoadICDebugBreak(MacroAssembler* masm) {
   // Register state for IC load call (from ic-x64.cc).
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   // -----------------------------------
-  Generate_DebugBreakCallHelper(masm, rcx.bit(), false);
+  Generate_DebugBreakCallHelper(masm, rax.bit() | rcx.bit(), false);
 }


=======================================
--- /branches/experimental/isolates/src/x64/full-codegen-x64.cc Mon May 31 21:48:19 2010 +++ /branches/experimental/isolates/src/x64/full-codegen-x64.cc Tue Jun 1 01:00:12 2010
@@ -1127,15 +1127,15 @@
     Comment cmnt(masm_, "Global variable");
     // Use inline caching. Variable name is passed in rcx and the global
     // object on the stack.
-    __ push(CodeGenerator::GlobalObject());
     __ Move(rcx, var->name());
+    __ movq(rax, CodeGenerator::GlobalObject());
     Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
     __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT);
     // A test rax instruction following the call is used by the IC to
     // indicate that the inobject property case was inlined.  Ensure there
     // is no test rax instruction here.
     __ nop();
-    DropAndApply(1, context, rax);
+    Apply(context, rax);

   } else if (slot != NULL && slot->type() == Slot::LOOKUP) {
     Comment cmnt(masm_, "Lookup slot");
@@ -1693,14 +1693,12 @@
   Comment cmnt(masm_, "[ Property");
   Expression* key = expr->key();

-  // Evaluate receiver.
-  VisitForValue(expr->obj(), kStack);
-
   if (key->IsPropertyName()) {
+    VisitForValue(expr->obj(), kAccumulator);
     EmitNamedPropertyLoad(expr);
-    // Drop receiver left on the stack by IC.
-    DropAndApply(1, context_, rax);
+    Apply(context_, rax);
   } else {
+    VisitForValue(expr->obj(), kStack);
     VisitForValue(expr->key(), kStack);
     EmitKeyedPropertyLoad(expr);
     // Drop key and receiver left on the stack by IC.
@@ -2745,13 +2743,13 @@
           !proxy->var()->is_this() &&
           proxy->var()->is_global()) {
         Comment cmnt(masm_, "Global variable");
-        __ push(CodeGenerator::GlobalObject());
         __ Move(rcx, proxy->name());
+        __ movq(rax, CodeGenerator::GlobalObject());
         Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
         // Use a regular load, not a contextual load, to avoid a reference
         // error.
         __ Call(ic, RelocInfo::CODE_TARGET);
-        __ movq(Operand(rsp, 0), rax);
+        __ push(rax);
       } else if (proxy != NULL &&
                  proxy->var()->slot() != NULL &&
                  proxy->var()->slot()->type() == Slot::LOOKUP) {
@@ -2861,10 +2859,12 @@
     if (expr->is_postfix() && context_ != Expression::kEffect) {
       __ Push(Smi::FromInt(0));
     }
-    VisitForValue(prop->obj(), kStack);
     if (assign_type == NAMED_PROPERTY) {
+      VisitForValue(prop->obj(), kAccumulator);
+      __ push(rax);  // Copy of receiver, needed for later store.
       EmitNamedPropertyLoad(prop);
     } else {
+      VisitForValue(prop->obj(), kStack);
       VisitForValue(prop->key(), kStack);
       EmitKeyedPropertyLoad(prop);
     }
=======================================
--- /branches/experimental/isolates/src/x64/ic-x64.cc Mon May 31 21:48:19 2010 +++ /branches/experimental/isolates/src/x64/ic-x64.cc Tue Jun 1 01:00:12 2010
@@ -56,18 +56,20 @@
                                    Register r1,
                                    Register r2,
                                    Register name,
+                                   Register r4,
                                    DictionaryCheck check_dictionary) {
   // Register use:
   //
   // r0   - used to hold the property dictionary.
   //
-  // r1   - initially the receiver
-  //      - used for the index into the property dictionary
+  // r1   - initially the receiver.
+  //      - unchanged on any jump to miss_label.
   //      - holds the result on exit.
   //
   // r2   - used to hold the capacity of the property dictionary.
   //
   // name - holds the name of the property and is unchanged.
+  // r4   - used to hold the index into the property dictionary.

   Label done;

@@ -116,19 +118,19 @@
       StringDictionary::kElementsStartIndex * kPointerSize;
   for (int i = 0; i < kProbes; i++) {
     // Compute the masked index: (hash + i + i * i) & mask.
-    __ movl(r1, FieldOperand(name, String::kHashFieldOffset));
-    __ shrl(r1, Immediate(String::kHashShift));
+    __ movl(r4, FieldOperand(name, String::kHashFieldOffset));
+    __ shrl(r4, Immediate(String::kHashShift));
     if (i > 0) {
-      __ addl(r1, Immediate(StringDictionary::GetProbeOffset(i)));
-    }
-    __ and_(r1, r2);
+      __ addl(r4, Immediate(StringDictionary::GetProbeOffset(i)));
+    }
+    __ and_(r4, r2);

     // Scale the index by multiplying by the entry size.
     ASSERT(StringDictionary::kEntrySize == 3);
-    __ lea(r1, Operand(r1, r1, times_2, 0));  // r1 = r1 * 3
+    __ lea(r4, Operand(r4, r4, times_2, 0));  // r4 = r4 * 3

     // Check if the key is identical to the name.
-    __ cmpq(name, Operand(r0, r1, times_pointer_size,
+    __ cmpq(name, Operand(r0, r4, times_pointer_size,
                           kElementsStartOffset - kHeapObjectTag));
     if (i != kProbes - 1) {
       __ j(equal, &done);
@@ -140,14 +142,14 @@
   // Check that the value is a normal property.
   __ bind(&done);
   const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
- __ Test(Operand(r0, r1, times_pointer_size, kDetailsOffset - kHeapObjectTag), + __ Test(Operand(r0, r4, times_pointer_size, kDetailsOffset - kHeapObjectTag),
           Smi::FromInt(PropertyDetails::TypeField::mask()));
   __ j(not_zero, miss_label);

   // Get the value at the masked, scaled index.
   const int kValueOffset = kElementsStartOffset + kPointerSize;
   __ movq(r1,
- Operand(r0, r1, times_pointer_size, kValueOffset - kHeapObjectTag)); + Operand(r0, r4, times_pointer_size, kValueOffset - kHeapObjectTag));
 }


@@ -501,6 +503,7 @@
                          rcx,
                          rdx,
                          rax,
+                         rdi,
                          DICTIONARY_CHECK_DONE);
   __ movq(rax, rcx);
   __ IncrementCounter(&Counters::keyed_load_generic_symbol, 1);
@@ -1228,7 +1231,7 @@
   // rsp[(argc + 1) * 8]    : argument 0 = receiver
   // -----------------------------------
   // Search dictionary - put result in register rdx.
-  GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, CHECK_DICTIONARY);
+ GenerateDictionaryLoad(masm, miss, rax, rdx, rbx, rcx, rdi, CHECK_DICTIONARY);

   // Move the result to register rdi and check that it isn't a smi.
   __ movq(rdi, rdx);
@@ -1333,13 +1336,13 @@

 void LoadIC::GenerateMiss(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------

   __ pop(rbx);
-  __ push(Operand(rsp, 0));  // receiver
+  __ push(rax);  // receiver
   __ push(rcx);  // name
   __ push(rbx);  // return address

@@ -1351,14 +1354,12 @@

 void LoadIC::GenerateArrayLength(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

-  __ movq(rax, Operand(rsp, kPointerSize));
-
   StubCompiler::GenerateLoadArrayLength(masm, rax, rdx, &miss);
   __ bind(&miss);
   StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@@ -1367,14 +1368,12 @@

 void LoadIC::GenerateFunctionPrototype(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

-  __ movq(rax, Operand(rsp, kPointerSize));
-
   StubCompiler::GenerateLoadFunctionPrototype(masm, rax, rdx, rbx, &miss);
   __ bind(&miss);
   StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
@@ -1383,13 +1382,11 @@

 void LoadIC::GenerateMegamorphic(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------

-  __ movq(rax, Operand(rsp, kPointerSize));
-
   // Probe the stub cache.
   Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC,
                                          NOT_IN_LOOP,
@@ -1403,14 +1400,12 @@

 void LoadIC::GenerateNormal(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss, probe, global;

-  __ movq(rax, Operand(rsp, kPointerSize));
-
   // Check that the receiver isn't a smi.
   __ JumpIfSmi(rax, &miss);

@@ -1432,7 +1427,8 @@

   // Search the dictionary placing the result in rax.
   __ bind(&probe);
- GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx, rcx, CHECK_DICTIONARY);
+  GenerateDictionaryLoad(masm, &miss, rdx, rax, rbx,
+                         rcx, rdi, CHECK_DICTIONARY);
   __ ret(0);

   // Global object access: Check access rights.
@@ -1440,23 +1436,20 @@
   __ CheckAccessGlobalProxy(rax, rdx, &miss);
   __ jmp(&probe);

-  // Cache miss: Restore receiver from stack and jump to runtime.
+  // Cache miss: Jump to runtime.
   __ bind(&miss);
-  __ movq(rax, Operand(rsp, 1 * kPointerSize));
   GenerateMiss(masm);
 }


 void LoadIC::GenerateStringLength(MacroAssembler* masm) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

-  __ movq(rax, Operand(rsp, kPointerSize));
-
   StubCompiler::GenerateLoadStringLength(masm, rax, rdx, rbx, &miss);
   __ bind(&miss);
   StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
=======================================
--- /branches/experimental/isolates/src/x64/stub-cache-x64.cc Mon May 31 21:48:19 2010 +++ /branches/experimental/isolates/src/x64/stub-cache-x64.cc Tue Jun 1 01:00:12 2010
@@ -1318,13 +1318,12 @@
                                               JSObject* holder,
                                               AccessorInfo* callback) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

-  __ movq(rax, Operand(rsp, kPointerSize));
   Failure* failure = Failure::InternalError();
   bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx,
                                       callback, name, &miss, &failure);
@@ -1343,13 +1342,12 @@
                                               Object* value,
                                               String* name) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

-  __ movq(rax, Operand(rsp, kPointerSize));
   GenerateLoadConstant(object, holder, rax, rbx, rdx, value, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
@@ -1363,15 +1361,12 @@
                                                  JSObject* object,
                                                  JSObject* last) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

-  // Load receiver.
-  __ movq(rax, Operand(rsp, kPointerSize));
-
   // Chech that receiver is not a smi.
   __ JumpIfSmi(rax, &miss);

@@ -1409,13 +1404,12 @@
                                            int index,
                                            String* name) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

-  __ movq(rax, Operand(rsp, kPointerSize));
   GenerateLoadField(object, holder, rax, rbx, rdx, index, name, &miss);
   __ bind(&miss);
   GenerateLoadMiss(masm(), Code::LOAD_IC);
@@ -1429,16 +1423,15 @@
                                                  JSObject* holder,
                                                  String* name) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

   LookupResult lookup;
   LookupPostInterceptor(holder, name, &lookup);

-  __ movq(rax, Operand(rsp, kPointerSize));
   // TODO(368): Compile in the whole chain: all the interceptors in
   // prototypes and ultimate answer.
   GenerateLoadInterceptor(receiver,
@@ -1465,15 +1458,12 @@
                                             String* name,
                                             bool is_dont_delete) {
   // ----------- S t a t e -------------
+  //  -- rax    : receiver
   //  -- rcx    : name
   //  -- rsp[0] : return address
-  //  -- rsp[8] : receiver
   // -----------------------------------
   Label miss;

-  // Get the receiver from the stack.
-  __ movq(rax, Operand(rsp, kPointerSize));
-
   // If the object is the holder then we know that it's a global
   // object which can only happen for contextual loads. In this case,
   // the receiver cannot be a smi.
@@ -1485,19 +1475,20 @@
   CheckPrototypes(object, rax, holder, rbx, rdx, name, &miss);

   // Get the value from the cell.
-  __ Move(rax, Handle<JSGlobalPropertyCell>(cell));
-  __ movq(rax, FieldOperand(rax, JSGlobalPropertyCell::kValueOffset));
+  __ Move(rbx, Handle<JSGlobalPropertyCell>(cell));
+  __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset));

   // Check for deleted property if property can actually be deleted.
   if (!is_dont_delete) {
-    __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
+    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
     __ j(equal, &miss);
   } else if (FLAG_debug_code) {
-    __ CompareRoot(rax, Heap::kTheHoleValueRootIndex);
+    __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
     __ Check(not_equal, "DontDelete cells can't contain the hole");
   }

   __ IncrementCounter(&Counters::named_load_global_inline, 1);
+  __ movq(rax, rbx);
   __ ret(0);

   __ bind(&miss);
=======================================
--- /branches/experimental/isolates/src/x64/virtual-frame-x64.cc Thu May 20 08:09:21 2010 +++ /branches/experimental/isolates/src/x64/virtual-frame-x64.cc Tue Jun 1 01:00:12 2010
@@ -1072,14 +1072,14 @@


 Result VirtualFrame::CallLoadIC(RelocInfo::Mode mode) {
-  // Name and receiver are on the top of the frame.  The IC expects
-  // name in rcx and receiver on the stack.  It does not drop the
-  // receiver.
+  // Name and receiver are on the top of the frame.  Both are dropped.
+  // The IC expects name in rcx and receiver in rax.
   Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize));
   Result name = Pop();
-  PrepareForCall(1, 0);  // One stack arg, not callee-dropped.
-  name.ToRegister(rcx);
-  name.Unuse();
+  Result receiver = Pop();
+  PrepareForCall(0, 0);  // One stack arg, not callee-dropped.
+  MoveResultsToRegisters(&name, &receiver, rcx, rax);
+
   return RawCallCodeObject(ic, mode);
 }

=======================================
--- /branches/experimental/isolates/test/mjsunit/delete.js Tue Sep 9 13:08:45 2008 +++ /branches/experimental/isolates/test/mjsunit/delete.js Tue Jun 1 01:00:12 2010
@@ -44,16 +44,11 @@
 assertTrue(delete x);
 assertTrue(typeof x === 'undefined', "x is gone");

-/****
- * This test relies on DontDelete attributes. This is not
- * working yet.
-
 var y = 87; // should have DontDelete attribute
 assertEquals(87, y);
 assertFalse(delete y, "don't delete");
 assertFalse(typeof y === 'undefined');
 assertEquals(87, y);
-*/

 var o = { x: 42, y: 87 };
 assertTrue(has(o, 'x'));
@@ -161,3 +156,25 @@
 assertFalse(has(a, Math.pow(2,30)-1), "delete 2^30-1");
 assertFalse(has(a, Math.pow(2,31)-1), "delete 2^31-1");
 assertEquals(Math.pow(2,31), a.length);
+
+// Check that a LoadIC for a dictionary field works, even
+// when the dictionary probe misses.
+function load_deleted_property_using_IC() {
+  var x = new Object();
+  x.a = 3;
+  x.b = 4;
+  x.c = 5;
+
+  delete x.c;
+  assertEquals(3, load_a(x));
+  assertEquals(3, load_a(x));
+  delete x.a;
+  assertTrue(typeof load_a(x) === 'undefined', "x.a is gone");
+  assertTrue(typeof load_a(x) === 'undefined', "x.a is gone");
+}
+
+function load_a(x) {
+  return x.a;
+}
+
+load_deleted_property_using_IC();

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to