Index: src/arm/stub-cache-arm.cc |
=================================================================== |
--- src/arm/stub-cache-arm.cc (revision 4423) |
+++ src/arm/stub-cache-arm.cc (working copy) |
@@ -600,6 +600,28 @@ |
} |
+// Generate code to check that a global property cell is empty. Create |
+// the property cell at compilation time if no cell exists for the |
+// property. |
+static Object* GenerateCheckPropertyCell(MacroAssembler* masm, |
+ GlobalObject* global, |
+ String* name, |
+ Register scratch, |
+ Label* miss) { |
+ Object* probe = global->EnsurePropertyCell(name); |
+ if (probe->IsFailure()) return probe; |
+ JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
+ ASSERT(cell->value()->IsTheHole()); |
+ __ mov(scratch, Operand(Handle<Object>(cell))); |
+ __ ldr(scratch, |
+ FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
+ __ cmp(scratch, ip); |
+ __ b(ne, miss); |
+ return cell; |
+} |
+ |
+ |
#undef __ |
#define __ ACCESS_MASM(masm()) |
@@ -620,23 +642,19 @@ |
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. |
+ // that their maps haven't changed. We also need to check that the |
+ // property cell for the property is still empty. |
while (object != holder) { |
if (object->IsGlobalObject()) { |
- GlobalObject* global = GlobalObject::cast(object); |
- Object* probe = global->EnsurePropertyCell(name); |
- if (probe->IsFailure()) { |
- set_failure(Failure::cast(probe)); |
+ Object* cell = GenerateCheckPropertyCell(masm(), |
+ GlobalObject::cast(object), |
+ name, |
+ scratch, |
+ miss); |
+ if (cell->IsFailure()) { |
+ set_failure(Failure::cast(cell)); |
return result; |
} |
- JSGlobalPropertyCell* cell = JSGlobalPropertyCell::cast(probe); |
- ASSERT(cell->value()->IsTheHole()); |
- __ mov(scratch, Operand(Handle<Object>(cell))); |
- __ ldr(scratch, |
- FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); |
- __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
- __ cmp(scratch, ip); |
- __ b(ne, miss); |
} |
object = JSObject::cast(object->GetPrototype()); |
} |
@@ -1389,6 +1407,46 @@ |
} |
+Object* LoadStubCompiler::CompileLoadNonexistent(String* name, |
+ JSObject* object, |
+ JSObject* last) { |
+ // ----------- S t a t e ------------- |
+ // -- r2 : name |
+ // -- lr : return address |
+ // -- [sp] : receiver |
+ // ----------------------------------- |
+ Label miss; |
+ |
+ // Load receiver. |
+ __ ldr(r0, MemOperand(sp, 0)); |
+ |
+ // Check the maps of the full prototype chain. |
+ CheckPrototypes(object, r0, last, r3, r1, name, &miss); |
+ |
+ // If the last object in the prototype chain is a global object, |
+ // check that the global property cell is empty. |
+ if (last->IsGlobalObject()) { |
+ Object* cell = GenerateCheckPropertyCell(masm(), |
+ GlobalObject::cast(last), |
+ name, |
+ r1, |
+ &miss); |
+ if (cell->IsFailure()) return cell; |
+ } |
+ |
+ // Return undefined if maps of the full prototype chain is still the |
Erik Corry
2010/04/15 10:28:44
maps ... is -> maps ... are
|
+ // same and no global property with this name contains a value. |
+ __ LoadRoot(r0, Heap::kUndefinedValueRootIndex); |
+ __ Ret(); |
+ |
+ __ bind(&miss); |
+ GenerateLoadMiss(masm(), Code::LOAD_IC); |
+ |
+ // Return the generated code. |
+ return GetCode(NONEXISTENT, Heap::empty_string()); |
+} |
+ |
+ |
Object* LoadStubCompiler::CompileLoadField(JSObject* object, |
JSObject* holder, |
int index, |