Author: [email protected]
Date: Fri Jul 10 02:40:47 2009
New Revision: 2425

Modified:
    branches/bleeding_edge/src/arm/stub-cache-arm.cc
    branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
    branches/bleeding_edge/src/objects-inl.h
    branches/bleeding_edge/src/objects.cc
    branches/bleeding_edge/src/objects.h
    branches/bleeding_edge/src/stub-cache.cc
    branches/bleeding_edge/src/stub-cache.h
    branches/bleeding_edge/src/x64/stub-cache-x64.cc

Log:
Re-enable ICs for loads and calls that skips a global object during
lookup through the prototype chain.
Review URL: http://codereview.chromium.org/155344

Modified: branches/bleeding_edge/src/arm/stub-cache-arm.cc
==============================================================================
--- branches/bleeding_edge/src/arm/stub-cache-arm.cc    (original)
+++ branches/bleeding_edge/src/arm/stub-cache-arm.cc    Fri Jul 10 02:40:47  
2009
@@ -171,110 +171,6 @@
  }


-void StubCompiler::GenerateLoadField(MacroAssembler* masm,
-                                     JSObject* object,
-                                     JSObject* holder,
-                                     Register receiver,
-                                     Register scratch1,
-                                     Register scratch2,
-                                     int index,
-                                     Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ tst(receiver, Operand(kSmiTagMask));
-  __ b(eq, miss_label);
-
-  // Check that the maps haven't changed.
-  Register reg =
-      masm->CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
-  GenerateFastPropertyLoad(masm, r0, reg, holder, index);
-  __ Ret();
-}
-
-
-void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
-                                        JSObject* object,
-                                        JSObject* holder,
-                                        Register receiver,
-                                        Register scratch1,
-                                        Register scratch2,
-                                        Object* value,
-                                        Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ tst(receiver, Operand(kSmiTagMask));
-  __ b(eq, miss_label);
-
-  // Check that the maps haven't changed.
-  Register reg =
-      masm->CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
-
-  // Return the constant value.
-  __ mov(r0, Operand(Handle<Object>(value)));
-  __ Ret();
-}
-
-
-void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
-                                        JSObject* object,
-                                        JSObject* holder,
-                                        Register receiver,
-                                        Register name,
-                                        Register scratch1,
-                                        Register scratch2,
-                                        AccessorInfo* callback,
-                                        Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ tst(receiver, Operand(kSmiTagMask));
-  __ b(eq, miss_label);
-
-  // Check that the maps haven't changed.
-  Register reg =
-      masm->CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
-
-  // Push the arguments on the JS stack of the caller.
-  __ push(receiver);  // receiver
-  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
-  __ push(ip);
-  __ push(name);  // name
-  __ push(reg);  // holder
-
-  // Do tail-call to the runtime system.
-  ExternalReference load_callback_property =
-      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
-  __ TailCallRuntime(load_callback_property, 4);
-}
-
-
-void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
-                                           JSObject* object,
-                                           JSObject* holder,
-                                           Smi* lookup_hint,
-                                           Register receiver,
-                                           Register name,
-                                           Register scratch1,
-                                           Register scratch2,
-                                           Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ tst(receiver, Operand(kSmiTagMask));
-  __ b(eq, miss_label);
-
-  // Check that the maps haven't changed.
-  Register reg =
-      masm->CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
-
-  // Push the arguments on the JS stack of the caller.
-  __ push(receiver);  // receiver
-  __ push(reg);  // holder
-  __ push(name);  // name
-  __ mov(scratch1, Operand(lookup_hint));
-  __ push(scratch1);
-
-  // Do tail-call to the runtime system.
-  ExternalReference load_ic_property =
-      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
-  __ TailCallRuntime(load_ic_property, 4);
-}
-
-
  void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
                                             Register receiver,
                                             Register scratch,
@@ -462,6 +358,147 @@
  #define __ ACCESS_MASM(masm())


+Register StubCompiler::CheckPrototypes(JSObject* object,
+                                       Register object_reg,
+                                       JSObject* holder,
+                                       Register holder_reg,
+                                       Register scratch,
+                                       String* name,
+                                       Label* miss) {
+  // Check that the maps haven't changed.
+  Register result =
+      masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch,  
miss);
+
+  // If we've skipped any global objects, it's not enough to verify
+  // that their maps haven't changed.
+  while (object != holder) {
+    if (object->IsGlobalObject()) {
+      GlobalObject* global = GlobalObject::cast(object);
+      Object* probe = global->EnsurePropertyCell(name);
+      if (probe->IsFailure()) {
+        set_failure(Failure::cast(probe));
+        return result;
+      }
+      JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
+      ASSERT(cell->value()->IsTheHole());
+      __ mov(scratch, Operand(Handle<Object>(cell)));
+      __ ldr(scratch,
+             FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset));
+      __ cmp(scratch, Operand(Factory::the_hole_value()));
+      __ b(ne, miss);
+    }
+    object = JSObject::cast(object->GetPrototype());
+  }
+
+  // Return the register containin the holder.
+  return result;
+}
+
+
+void StubCompiler::GenerateLoadField(JSObject* object,
+                                     JSObject* holder,
+                                     Register receiver,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     int index,
+                                     String* name,
+                                     Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name,  
miss);
+  GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadConstant(JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Object* value,
+                                        String* name,
+                                        Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name,  
miss);
+
+  // Return the constant value.
+  __ mov(r0, Operand(Handle<Object>(value)));
+  __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadCallback(JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register name_reg,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        AccessorInfo* callback,
+                                        String* name,
+                                        Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name,  
miss);
+
+  // Push the arguments on the JS stack of the caller.
+  __ push(receiver);  // receiver
+  __ mov(ip, Operand(Handle<AccessorInfo>(callback)));  // callback data
+  __ push(ip);
+  __ push(name_reg);  // name
+  __ push(reg);  // holder
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_callback_property =
+      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+  __ TailCallRuntime(load_callback_property, 4);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(JSObject* object,
+                                           JSObject* holder,
+                                           Smi* lookup_hint,
+                                           Register receiver,
+                                           Register name_reg,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           String* name,
+                                           Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ tst(receiver, Operand(kSmiTagMask));
+  __ b(eq, miss);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      CheckPrototypes(object, receiver, holder, scratch1, scratch2, name,  
miss);
+
+  // Push the arguments on the JS stack of the caller.
+  __ push(receiver);  // receiver
+  __ push(reg);  // holder
+  __ push(name_reg);  // name
+  __ mov(scratch1, Operand(lookup_hint));
+  __ push(scratch1);
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_ic_property =
+      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+  __ TailCallRuntime(load_ic_property, 4);
+}
+
+
  Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
    // ----------- S t a t e -------------
    //  -- r1: function
@@ -513,7 +550,7 @@

    // Do the right check and compute the holder register.
    Register reg =
-      masm()->CheckMaps(JSObject::cast(object), r0, holder, r3, r2, &miss);
+      CheckPrototypes(JSObject::cast(object), r0, holder, r3, r2, name,  
&miss);
    GenerateFastPropertyLoad(masm(), r1, reg, holder, index);

    // Check that the function really is a function.
@@ -546,6 +583,7 @@
  Object* CallStubCompiler::CompileCallConstant(Object* object,
                                                JSObject* holder,
                                                JSFunction* function,
+                                              String* name,
                                                CheckType check) {
    // ----------- S t a t e -------------
    //  -- lr: return address
@@ -569,7 +607,7 @@
    switch (check) {
      case RECEIVER_MAP_CHECK:
        // Check that the maps haven't changed.
-      __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
+      CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name,  
&miss);

        // Patch the receiver on the stack with the global proxy if
        // necessary.
@@ -587,8 +625,8 @@
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::STRING_FUNCTION_INDEX,
                                            r2);
-      __ CheckMaps(JSObject::cast(object->GetPrototype()),
-                   r2, holder, r3, r1, &miss);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder,  
r3,
+                      r1, name, &miss);
        break;

      case NUMBER_CHECK: {
@@ -603,8 +641,8 @@
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::NUMBER_FUNCTION_INDEX,
                                            r2);
-      __ CheckMaps(JSObject::cast(object->GetPrototype()),
-                   r2, holder, r3, r1, &miss);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder,  
r3,
+                      r1, name, &miss);
        break;
      }

@@ -620,13 +658,13 @@
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::BOOLEAN_FUNCTION_INDEX,
                                            r2);
-      __ CheckMaps(JSObject::cast(object->GetPrototype()),
-                   r2, holder, r3, r1, &miss);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder,  
r3,
+                      r1, name, &miss);
        break;
      }

      case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
-      __ CheckMaps(JSObject::cast(object), r1, holder, r3, r2, &miss);
+      CheckPrototypes(JSObject::cast(object), r1, holder, r3, r2, name,  
&miss);
        // Make sure object->elements()->map() != Heap::hash_table_map()
        // Get the elements array of the object.
        __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
@@ -712,7 +750,7 @@
    }

    // Check that the maps haven't changed.
-  masm()->CheckMaps(object, r0, holder, r3, r2, &miss);
+  CheckPrototypes(object, r0, holder, r3, r2, name, &miss);

    // Get the value from the cell.
    __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
@@ -941,7 +979,7 @@

    __ ldr(r0, MemOperand(sp, 0));

-  GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
+  GenerateLoadField(object, holder, r0, r3, r1, index, name, &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::LOAD_IC);

@@ -962,7 +1000,7 @@
    Label miss;

    __ ldr(r0, MemOperand(sp, 0));
-  GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback,  
&miss);
+  GenerateLoadCallback(object, holder, r0, r2, r3, r1, callback, name,  
&miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::LOAD_IC);

@@ -984,7 +1022,7 @@

    __ ldr(r0, MemOperand(sp, 0));

-  GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
+  GenerateLoadConstant(object, holder, r0, r3, r1, value, name, &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::LOAD_IC);

@@ -1005,14 +1043,14 @@

    __ ldr(r0, MemOperand(sp, 0));

-  GenerateLoadInterceptor(masm(),
-                          object,
+  GenerateLoadInterceptor(object,
                            holder,
                            holder->InterceptorPropertyLookupHint(name),
                            r0,
                            r2,
                            r3,
                            r1,
+                          name,
                            &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::LOAD_IC);
@@ -1048,7 +1086,7 @@
    }

    // Check that the map of the global has not changed.
-  masm()->CheckMaps(object, r1, holder, r3, r0, &miss);
+  CheckPrototypes(object, r1, holder, r3, r0, name, &miss);

    // Get the value from the cell.
    __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
@@ -1091,7 +1129,7 @@
    __ cmp(r2, Operand(Handle<String>(name)));
    __ b(ne, &miss);

-  GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
+  GenerateLoadField(receiver, holder, r0, r3, r1, index, name, &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);

@@ -1116,8 +1154,7 @@
    __ cmp(r2, Operand(Handle<String>(name)));
    __ b(ne, &miss);

-  GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
-                       r1, callback, &miss);
+  GenerateLoadCallback(receiver, holder, r0, r2, r3, r1, callback, name,  
&miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);

@@ -1143,7 +1180,7 @@
    __ cmp(r2, Operand(Handle<String>(name)));
    __ b(ne, &miss);

-  GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
+  GenerateLoadConstant(receiver, holder, r0, r3, r1, value, name, &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);

@@ -1169,14 +1206,14 @@
    __ cmp(r2, Operand(Handle<String>(name)));
    __ b(ne, &miss);

-  GenerateLoadInterceptor(masm(),
-                          receiver,
+  GenerateLoadInterceptor(receiver,
                            holder,
                            Smi::FromInt(JSObject::kLookupInHolder),
                            r0,
                            r2,
                            r3,
                            r1,
+                          name,
                            &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);

Modified: branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
==============================================================================
--- branches/bleeding_edge/src/ia32/stub-cache-ia32.cc  (original)
+++ branches/bleeding_edge/src/ia32/stub-cache-ia32.cc  Fri Jul 10 02:40:47  
2009
@@ -273,114 +273,6 @@
  }


-void StubCompiler::GenerateLoadField(MacroAssembler* masm,
-                                     JSObject* object,
-                                     JSObject* holder,
-                                     Register receiver,
-                                     Register scratch1,
-                                     Register scratch2,
-                                     int index,
-                                     Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ test(receiver, Immediate(kSmiTagMask));
-  __ j(zero, miss_label, not_taken);
-
-  // Check that the maps haven't changed.
-  Register reg =
-      masm->CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
-
-  // Get the value from the properties.
-  GenerateFastPropertyLoad(masm, eax, reg, holder, index);
-  __ ret(0);
-}
-
-
-void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
-                                        JSObject* object,
-                                        JSObject* holder,
-                                        Register receiver,
-                                        Register name,
-                                        Register scratch1,
-                                        Register scratch2,
-                                        AccessorInfo* callback,
-                                        Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ test(receiver, Immediate(kSmiTagMask));
-  __ j(zero, miss_label, not_taken);
-
-  // Check that the maps haven't changed.
-  Register reg =
-      masm->CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
-
-  // Push the arguments on the JS stack of the caller.
-  __ pop(scratch2);  // remove return address
-  __ push(receiver);  // receiver
-  __ push(Immediate(Handle<AccessorInfo>(callback)));  // callback data
-  __ push(name);  // name
-  __ push(reg);  // holder
-  __ push(scratch2);  // restore return address
-
-  // Do tail-call to the runtime system.
-  ExternalReference load_callback_property =
-      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
-  __ TailCallRuntime(load_callback_property, 4);
-}
-
-
-void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
-                                        JSObject* object,
-                                        JSObject* holder,
-                                        Register receiver,
-                                        Register scratch1,
-                                        Register scratch2,
-                                        Object* value,
-                                        Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ test(receiver, Immediate(kSmiTagMask));
-  __ j(zero, miss_label, not_taken);
-
-  // Check that the maps haven't changed.
-  Register reg =
-      masm->CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
-
-  // Return the constant value.
-  __ mov(eax, Handle<Object>(value));
-  __ ret(0);
-}
-
-
-void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
-                                           JSObject* object,
-                                           JSObject* holder,
-                                           Smi* lookup_hint,
-                                           Register receiver,
-                                           Register name,
-                                           Register scratch1,
-                                           Register scratch2,
-                                           Label* miss_label) {
-  // Check that the receiver isn't a smi.
-  __ test(receiver, Immediate(kSmiTagMask));
-  __ j(zero, miss_label, not_taken);
-
-  // Check that the maps haven't changed.
-  Register reg =
-      masm->CheckMaps(object, receiver, holder, scratch1, scratch2,  
miss_label);
-
-  // Push the arguments on the JS stack of the caller.
-  __ pop(scratch2);  // remove return address
-  __ push(receiver);  // receiver
-  __ push(reg);  // holder
-  __ push(name);  // name
-  // TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
-  // LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
-  __ push(Immediate(lookup_hint));
-  __ push(scratch2);  // restore return address
-
-  // Do tail-call to the runtime system.
-  ExternalReference load_ic_property =
-      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
-  __ TailCallRuntime(load_ic_property, 4);
-}


  void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind)  
{
@@ -474,10 +366,159 @@


  #undef __
-
  #define __ ACCESS_MASM(masm())


+Register StubCompiler::CheckPrototypes(JSObject* object,
+                                       Register object_reg,
+                                       JSObject* holder,
+                                       Register holder_reg,
+                                       Register scratch,
+                                       String* name,
+                                       Label* miss) {
+  // Check that the maps haven't changed.
+  Register result =
+      masm()->CheckMaps(object, object_reg, holder, holder_reg, scratch,  
miss);
+
+  // If we've skipped any global objects, it's not enough to verify
+  // that their maps haven't changed.
+  while (object != holder) {
+    if (object->IsGlobalObject()) {
+      GlobalObject* global = GlobalObject::cast(object);
+      Object* probe = global->EnsurePropertyCell(name);
+      if (probe->IsFailure()) {
+        set_failure(Failure::cast(probe));
+        return result;
+      }
+      JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe);
+      ASSERT(cell->value()->IsTheHole());
+      __ mov(scratch, Immediate(Handle<Object>(cell)));
+      __ cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset),
+             Immediate(Factory::the_hole_value()));
+      __ j(not_equal, miss, not_taken);
+    }
+    object = JSObject::cast(object->GetPrototype());
+  }
+
+  // Return the register containin the holder.
+  return result;
+}
+
+
+void StubCompiler::GenerateLoadField(JSObject* object,
+                                     JSObject* holder,
+                                     Register receiver,
+                                     Register scratch1,
+                                     Register scratch2,
+                                     int index,
+                                     String* name,
+                                     Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss, not_taken);
+
+  // Check the prototype chain.
+  Register reg =
+      CheckPrototypes(object, receiver, holder,
+                      scratch1, scratch2, name, miss);
+
+  // Get the value from the properties.
+  GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
+  __ ret(0);
+}
+
+
+void StubCompiler::GenerateLoadCallback(JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register name_reg,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        AccessorInfo* callback,
+                                        String* name,
+                                        Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss, not_taken);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      CheckPrototypes(object, receiver, holder,
+                      scratch1, scratch2, name, miss);
+
+  // Push the arguments on the JS stack of the caller.
+  __ pop(scratch2);  // remove return address
+  __ push(receiver);  // receiver
+  __ push(Immediate(Handle<AccessorInfo>(callback)));  // callback data
+  __ push(name_reg);  // name
+  __ push(reg);  // holder
+  __ push(scratch2);  // restore return address
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_callback_property =
+      ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+  __ TailCallRuntime(load_callback_property, 4);
+}
+
+
+void StubCompiler::GenerateLoadConstant(JSObject* object,
+                                        JSObject* holder,
+                                        Register receiver,
+                                        Register scratch1,
+                                        Register scratch2,
+                                        Object* value,
+                                        String* name,
+                                        Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss, not_taken);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      CheckPrototypes(object, receiver, holder,
+                      scratch1, scratch2, name, miss);
+
+  // Return the constant value.
+  __ mov(eax, Handle<Object>(value));
+  __ ret(0);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(JSObject* object,
+                                           JSObject* holder,
+                                           Smi* lookup_hint,
+                                           Register receiver,
+                                           Register name_reg,
+                                           Register scratch1,
+                                           Register scratch2,
+                                           String* name,
+                                           Label* miss) {
+  // Check that the receiver isn't a smi.
+  __ test(receiver, Immediate(kSmiTagMask));
+  __ j(zero, miss, not_taken);
+
+  // Check that the maps haven't changed.
+  Register reg =
+      CheckPrototypes(object, receiver, holder,
+                      scratch1, scratch2, name, miss);
+
+  // Push the arguments on the JS stack of the caller.
+  __ pop(scratch2);  // remove return address
+  __ push(receiver);  // receiver
+  __ push(reg);  // holder
+  __ push(name_reg);  // name
+  // TODO(367): Maybe don't push lookup_hint for LOOKUP_IN_HOLDER and/or
+  // LOOKUP_IN_PROTOTYPE, but use a special version of lookup method?
+  __ push(Immediate(lookup_hint));
+  __ push(scratch2);  // restore return address
+
+  // Do tail-call to the runtime system.
+  ExternalReference load_ic_property =
+      ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+  __ TailCallRuntime(load_ic_property, 4);
+}
+
+
  // TODO(1241006): Avoid having lazy compile stubs specialized by the
  // number of arguments. It is not needed anymore.
  Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
@@ -520,7 +561,8 @@

    // Do the right check and compute the holder register.
    Register reg =
-      masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx,  
&miss);
+      CheckPrototypes(JSObject::cast(object), edx, holder,
+                      ebx, ecx, name, &miss);

    GenerateFastPropertyLoad(masm(), edi, reg, holder, index);

@@ -553,6 +595,7 @@
  Object* CallStubCompiler::CompileCallConstant(Object* object,
                                                JSObject* holder,
                                                JSFunction* function,
+                                              String* name,
                                                CheckType check) {
    // ----------- S t a t e -------------
    // -----------------------------------
@@ -575,7 +618,8 @@
    switch (check) {
      case RECEIVER_MAP_CHECK:
        // Check that the maps haven't changed.
-      __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+      CheckPrototypes(JSObject::cast(object), edx, holder,
+                      ebx, ecx, name, &miss);

        // Patch the receiver on the stack with the global proxy if
        // necessary.
@@ -595,8 +639,8 @@
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::STRING_FUNCTION_INDEX,
                                            ecx);
-      __ CheckMaps(JSObject::cast(object->GetPrototype()),
-                   ecx, holder, ebx, edx, &miss);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
+                      ebx, edx, name, &miss);
        break;

      case NUMBER_CHECK: {
@@ -611,8 +655,8 @@
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::NUMBER_FUNCTION_INDEX,
                                            ecx);
-      __ CheckMaps(JSObject::cast(object->GetPrototype()),
-                   ecx, holder, ebx, edx, &miss);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
+                      ebx, edx, name, &miss);
        break;
      }

@@ -628,13 +672,14 @@
        GenerateLoadGlobalFunctionPrototype(masm(),
                                            Context::BOOLEAN_FUNCTION_INDEX,
                                            ecx);
-      __ CheckMaps(JSObject::cast(object->GetPrototype()),
-                   ecx, holder, ebx, edx, &miss);
+      CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
+                      ebx, edx, name, &miss);
        break;
      }

      case JSARRAY_HAS_FAST_ELEMENTS_CHECK:
-      __ CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx, &miss);
+      CheckPrototypes(JSObject::cast(object), edx, holder,
+                      ebx, ecx, name, &miss);
        // Make sure object->elements()->map() !=  
Heap::dictionary_array_map()
        // Get the elements array of the object.
        __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
@@ -692,7 +737,8 @@

    // Check that maps have not changed and compute the holder register.
    Register reg =
-      masm()->CheckMaps(JSObject::cast(object), edx, holder, ebx, ecx,  
&miss);
+      CheckPrototypes(JSObject::cast(object), edx, holder,
+                      ebx, ecx, name, &miss);

    // Enter an internal frame.
    __ EnterInternalFrame();
@@ -771,7 +817,7 @@
    }

    // Check that the maps haven't changed.
-  masm()->CheckMaps(object, edx, holder, ebx, ecx, &miss);
+  CheckPrototypes(object, edx, holder, ebx, ecx, name, &miss);

    // Get the value from the cell.
    __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell)));
@@ -1033,6 +1079,7 @@
  }


+
  Object* LoadStubCompiler::CompileLoadField(JSObject* object,
                                             JSObject* holder,
                                             int index,
@@ -1045,7 +1092,7 @@
    Label miss;

    __ mov(eax, (Operand(esp, kPointerSize)));
-  GenerateLoadField(masm(), object, holder, eax, ebx, edx, index, &miss);
+  GenerateLoadField(object, holder, eax, ebx, edx, index, name, &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::LOAD_IC);

@@ -1066,8 +1113,8 @@
    Label miss;

    __ mov(eax, (Operand(esp, kPointerSize)));
-  GenerateLoadCallback(masm(), object, holder, eax, ecx, ebx,
-                       edx, callback, &miss);
+  GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
+                       callback, name, &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::LOAD_IC);

@@ -1088,7 +1135,7 @@
    Label miss;

    __ mov(eax, (Operand(esp, kPointerSize)));
-  GenerateLoadConstant(masm(), object, holder, eax, ebx, edx, value,  
&miss);
+  GenerateLoadConstant(object, holder, eax, ebx, edx, value, name, &miss);
    __ bind(&miss);
    GenerateLoadMiss(masm(), Code::LOAD_IC);

@@ -1110,14 +1157,14 @@
    __ mov(eax, (Operand(esp, kPointerSize)));
    // TODO(368): Compile in the whole chain: all the interceptors in
    // prototypes and ultimate answer.
-  GenerateLoadInterceptor(masm(),
-                          receiver,
+  GenerateLoadInterceptor(receiver,
                            holder,
                            holder->InterceptorPropertyLookupHint(name),
                            eax,
                            ecx,
                            edx,
                            ebx,
+                          name,
                            &miss);

    __ bind(&miss);
@@ -1154,7 +1201,7 @@
    }

    // Check that the maps haven't changed.
-  masm()->CheckMaps(object, eax, holder, ebx, edx, &miss);
+  CheckPrototypes(object, eax, holder, ebx, edx, name, &miss);

    // Get the value from the cell.
    __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell)));
@@ -1200,7 +1247,8 @@
    __ cmp(Operand(eax), Immediate(Handle<String>(name)));
    __ j(not_equal, &miss, not_taken);

-  GenerateLoadField(masm(), receiver, holder, ecx, ebx, edx, index, &miss);
+  GenerateLoadField(receiver, holder, ecx, ebx, edx, index, name, &miss);
+
    __ bind(&miss);
    __ DecrementCounter(&Counters::keyed_load_field, 1);
    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
@@ -1229,8 +1277,8 @@
    __ cmp(Operand(eax), Immediate(Handle<String>(name)));
    __ j(not_equal, &miss, not_taken);

-  GenerateLoadCallback(masm(), receiver, holder, ecx, eax, ebx, edx,
-                       callback, &miss);
+  GenerateLoadCallback(receiver, holder, ecx, eax, ebx, edx,
+                       callback, name, &miss);
    __ bind(&miss);
    __ DecrementCounter(&Counters::keyed_load_callback, 1);
    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
@@ -1259,7 +1307,8 @@
    __ cmp(Operand(eax), Immediate(Handle<String>(name)));
    __ j(not_equal, &miss, not_taken);

-  GenerateLoadConstant(masm(), receiver, holder, ecx, ebx, edx, value,  
&miss);
+  GenerateLoadConstant(receiver, holder, ecx, ebx, edx,
+                       value, name, &miss);
    __ bind(&miss);
    __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
    GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
@@ -1287,14 +1336,14 @@
    __ cmp(Operand(eax), Immediate(Handle<String>(name)));
    __ j(not_equal, &miss, not_taken);

-  GenerateLoadInterceptor(masm(),
-                          receiver,
+  GenerateLoadInterceptor(receiver,
                            holder,
                            Smi::FromInt(JSObject::kLookupInHolder),
                            ecx,
                            eax,
                            edx,
                            ebx,
+                          name,
                            &miss);
    __ bind(&miss);
    __ DecrementCounter(&Counters::keyed_load_interceptor, 1);

Modified: branches/bleeding_edge/src/objects-inl.h
==============================================================================
--- branches/bleeding_edge/src/objects-inl.h    (original)
+++ branches/bleeding_edge/src/objects-inl.h    Fri Jul 10 02:40:47 2009
@@ -2653,7 +2653,7 @@
                                        Object* key,
                                        Object* value,
                                        PropertyDetails details) {
-  ASSERT(!key->IsString() || details.index() > 0);
+  ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
    int index = HashTable<Shape, Key>::EntryToIndex(entry);
    WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
    FixedArray::set(index, key, mode);

Modified: branches/bleeding_edge/src/objects.cc
==============================================================================
--- branches/bleeding_edge/src/objects.cc       (original)
+++ branches/bleeding_edge/src/objects.cc       Fri Jul 10 02:40:47 2009
@@ -436,8 +436,7 @@
        store_value = Heap::AllocateJSGlobalPropertyCell(value);
        if (store_value->IsFailure()) return store_value;
      }
-    Object* dict =
-        property_dictionary()->Add(name, store_value, details);
+    Object* dict = property_dictionary()->Add(name, store_value, details);
      if (dict->IsFailure()) return dict;
      set_properties(StringDictionary::cast(dict));
      return value;
@@ -1712,30 +1711,24 @@
    } else {
      int entry = property_dictionary()->FindEntry(name);
      if (entry != StringDictionary::kNotFound) {
-      // Make sure to disallow caching for uninitialized constants
-      // found in the dictionary-mode objects.
        Object* value = property_dictionary()->ValueAt(entry);
        if (IsGlobalObject()) {
          PropertyDetails d = property_dictionary()->DetailsAt(entry);
          if (d.IsDeleted()) {
-          // We've skipped a global object during lookup, so we cannot
-          // use inline caching because the map of the global object
-          // doesn't change if the property should be re-added.
-          result->DisallowCaching();
            result->NotFound();
            return;
          }
          value = JSGlobalPropertyCell::cast(value)->value();
          ASSERT(result->IsLoaded());
        }
-      if (value->IsTheHole()) {
-        result->DisallowCaching();
-      }
+      // Make sure to disallow caching for uninitialized constants
+      // found in the dictionary-mode objects.
+      if (value->IsTheHole()) result->DisallowCaching();
        result->DictionaryResult(this, entry);
        return;
      }
      // Slow case object skipped during lookup. Do not use inline caching.
-    result->DisallowCaching();
+    if (!IsGlobalObject()) result->DisallowCaching();
    }
    result->NotFound();
  }
@@ -6841,6 +6834,26 @@
  }


+Object* GlobalObject::EnsurePropertyCell(String* name) {
+  ASSERT(!HasFastProperties());
+  int entry = property_dictionary()->FindEntry(name);
+  if (entry == StringDictionary::kNotFound) {
+    Object* cell =  
Heap::AllocateJSGlobalPropertyCell(Heap::the_hole_value());
+    if (cell->IsFailure()) return cell;
+    PropertyDetails details(NONE, NORMAL);
+    details = details.AsDeleted();
+    Object* dictionary = property_dictionary()->Add(name, cell, details);
+    if (dictionary->IsFailure()) return dictionary;
+    set_properties(StringDictionary::cast(dictionary));
+    return cell;
+  } else {
+    Object* value = property_dictionary()->ValueAt(entry);
+    ASSERT(value->IsJSGlobalPropertyCell());
+    return value;
+  }
+}
+
+
  Object* SymbolTable::LookupString(String* string, Object** s) {
    SymbolKey key(string);
    return LookupKey(&key, s);
@@ -7200,7 +7213,7 @@

    uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
    // Insert element at empty or deleted entry
-  if (details.index() == 0 && Shape::kIsEnumerable) {
+  if (!details.IsDeleted() && details.index() == 0 &&  
Shape::kIsEnumerable) {
      // Assign an enumeration index to the property and update
      // SetNextEnumerationIndex.
      int index = NextEnumerationIndex();
@@ -7273,7 +7286,9 @@
    for (int i = 0; i < capacity; i++) {
      Object* k = HashTable<Shape, Key>::KeyAt(i);
      if (HashTable<Shape, Key>::IsKey(k)) {
-      PropertyAttributes attr = DetailsAt(i).attributes();
+      PropertyDetails details = DetailsAt(i);
+      if (details.IsDeleted()) continue;
+      PropertyAttributes attr = details.attributes();
        if ((attr & filter) == 0) result++;
      }
    }
@@ -7297,7 +7312,9 @@
    for (int i = 0; i < capacity; i++) {
       Object* k = HashTable<Shape, Key>::KeyAt(i);
       if (HashTable<Shape, Key>::IsKey(k)) {
-       PropertyAttributes attr = DetailsAt(i).attributes();
+       PropertyDetails details = DetailsAt(i);
+       if (details.IsDeleted()) continue;
+       PropertyAttributes attr = details.attributes();
         if ((attr & filter) == 0) storage->set(index++, k);
       }
    }
@@ -7315,13 +7332,12 @@
       Object* k = KeyAt(i);
       if (IsKey(k)) {
         PropertyDetails details = DetailsAt(i);
-       if (!details.IsDontEnum()) {
-         storage->set(index, k);
-         sort_array->set(index,
-                         Smi::FromInt(details.index()),
-                         SKIP_WRITE_BARRIER);
-         index++;
-       }
+       if (details.IsDeleted() || details.IsDontEnum()) continue;
+       storage->set(index, k);
+       sort_array->set(index,
+                       Smi::FromInt(details.index()),
+                       SKIP_WRITE_BARRIER);
+       index++;
       }
    }
    storage->SortPairs(sort_array, sort_array->length());
@@ -7338,6 +7354,8 @@
    for (int i = 0; i < capacity; i++) {
      Object* k = HashTable<Shape, Key>::KeyAt(i);
      if (HashTable<Shape, Key>::IsKey(k)) {
+      PropertyDetails details = DetailsAt(i);
+      if (details.IsDeleted()) continue;
        storage->set(index++, k);
      }
    }

Modified: branches/bleeding_edge/src/objects.h
==============================================================================
--- branches/bleeding_edge/src/objects.h        (original)
+++ branches/bleeding_edge/src/objects.h        Fri Jul 10 02:40:47 2009
@@ -3240,6 +3240,9 @@
    // Retrieve the property cell used to store a property.
    Object* GetPropertyCell(LookupResult* result);

+  // Ensure that the global object has a cell for the given property name.
+  Object* EnsurePropertyCell(String* name);
+
    // Casting.
    static inline GlobalObject* cast(Object* obj);


Modified: branches/bleeding_edge/src/stub-cache.cc
==============================================================================
--- branches/bleeding_edge/src/stub-cache.cc    (original)
+++ branches/bleeding_edge/src/stub-cache.cc    Fri Jul 10 02:40:47 2009
@@ -450,7 +450,7 @@
      if (!function->is_compiled()) return Failure::InternalError();
      // Compile the stub - only create stubs for fully compiled functions.
      CallStubCompiler compiler(argc, in_loop);
-    code = compiler.CompileCallConstant(object, holder, function, check);
+    code = compiler.CompileCallConstant(object, holder, function, name,  
check);
      if (code->IsFailure()) return code;
      ASSERT_EQ(flags, Code::cast(code)->flags());
      LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
@@ -957,6 +957,10 @@


  Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char*  
name) {
+  // Check for allocation failures during stub compilation.
+  if (failure_->IsFailure()) return failure_;
+
+  // Create code object in the heap.
    CodeDesc desc;
    masm_.GetCode(&desc);
    Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject());

Modified: branches/bleeding_edge/src/stub-cache.h
==============================================================================
--- branches/bleeding_edge/src/stub-cache.h     (original)
+++ branches/bleeding_edge/src/stub-cache.h     Fri Jul 10 02:40:47 2009
@@ -324,7 +324,7 @@
      JSARRAY_HAS_FAST_ELEMENTS_CHECK
    };

-  StubCompiler() : scope_(), masm_(NULL, 256) { }
+  StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }

    Object* CompileCallInitialize(Code::Flags flags);
    Object* CompileCallPreMonomorphic(Code::Flags flags);
@@ -344,40 +344,7 @@
    static void GenerateFastPropertyLoad(MacroAssembler* masm,
                                         Register dst, Register src,
                                         JSObject* holder, int index);
-  static void GenerateLoadField(MacroAssembler* masm,
-                                JSObject* object,
-                                JSObject* holder,
-                                Register receiver,
-                                Register scratch1,
-                                Register scratch2,
-                                int index,
-                                Label* miss_label);
-  static void GenerateLoadCallback(MacroAssembler* masm,
-                                   JSObject* object,
-                                   JSObject* holder,
-                                   Register receiver,
-                                   Register name,
-                                   Register scratch1,
-                                   Register scratch2,
-                                   AccessorInfo* callback,
-                                   Label* miss_label);
-  static void GenerateLoadConstant(MacroAssembler* masm,
-                                   JSObject* object,
-                                   JSObject* holder,
-                                   Register receiver,
-                                   Register scratch1,
-                                   Register scratch2,
-                                   Object* value,
-                                   Label* miss_label);
-  static void GenerateLoadInterceptor(MacroAssembler* masm,
-                                      JSObject* object,
-                                      JSObject* holder,
-                                      Smi* lookup_hint,
-                                      Register receiver,
-                                      Register name,
-                                      Register scratch1,
-                                      Register scratch2,
-                                      Label* miss_label);
+
    static void GenerateLoadArrayLength(MacroAssembler* masm,
                                        Register receiver,
                                        Register scratch,
@@ -412,10 +379,60 @@
    Object* GetCodeWithFlags(Code::Flags flags, String* name);

    MacroAssembler* masm() { return &masm_; }
+  void set_failure(Failure* failure) { failure_ = failure; }
+
+  // Check the integrity of the prototype chain to make sure that the
+  // current IC is still valid.
+  Register CheckPrototypes(JSObject* object,
+                           Register object_reg,
+                           JSObject* holder,
+                           Register holder_reg,
+                           Register scratch,
+                           String* name,
+                           Label* miss);
+
+  void GenerateLoadField(JSObject* object,
+                         JSObject* holder,
+                         Register receiver,
+                         Register scratch1,
+                         Register scratch2,
+                         int index,
+                         String* name,
+                         Label* miss);
+
+  void GenerateLoadCallback(JSObject* object,
+                            JSObject* holder,
+                            Register receiver,
+                            Register name_reg,
+                            Register scratch1,
+                            Register scratch2,
+                            AccessorInfo* callback,
+                            String* name,
+                            Label* miss);
+
+  void GenerateLoadConstant(JSObject* object,
+                            JSObject* holder,
+                            Register receiver,
+                            Register scratch1,
+                            Register scratch2,
+                            Object* value,
+                            String* name,
+                            Label* miss);
+
+  void GenerateLoadInterceptor(JSObject* object,
+                               JSObject* holder,
+                               Smi* lookup_hint,
+                               Register receiver,
+                               Register name_reg,
+                               Register scratch1,
+                               Register scratch2,
+                               String* name,
+                               Label* miss);

   private:
    HandleScope scope_;
    MacroAssembler masm_;
+  Failure* failure_;
  };


@@ -518,6 +535,7 @@
    Object* CompileCallConstant(Object* object,
                                JSObject* holder,
                                JSFunction* function,
+                              String* name,
                                CheckType check);
    Object* CompileCallInterceptor(Object* object,
                                   JSObject* holder,

Modified: branches/bleeding_edge/src/x64/stub-cache-x64.cc
==============================================================================
--- branches/bleeding_edge/src/x64/stub-cache-x64.cc    (original)
+++ branches/bleeding_edge/src/x64/stub-cache-x64.cc    Fri Jul 10 02:40:47  
2009
@@ -42,7 +42,8 @@
  Object* CallStubCompiler::CompileCallConstant(Object* a,
                                                JSObject* b,
                                                JSFunction* c,
-                                              StubCompiler::CheckType d) {
+                                              String* d,
+                                              StubCompiler::CheckType e) {
    UNIMPLEMENTED();
    return NULL;
  }

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

Reply via email to