Chromium Code Reviews| 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, |