Commit 875dbe65 authored by kasperl@chromium.org's avatar kasperl@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2425 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 15754c6f
...@@ -171,110 +171,6 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, ...@@ -171,110 +171,6 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
} }
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, void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
Register receiver, Register receiver,
Register scratch, Register scratch,
...@@ -462,6 +358,147 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { ...@@ -462,6 +358,147 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
#define __ ACCESS_MASM(masm()) #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) { Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r1: function // -- r1: function
...@@ -513,7 +550,7 @@ Object* CallStubCompiler::CompileCallField(Object* object, ...@@ -513,7 +550,7 @@ Object* CallStubCompiler::CompileCallField(Object* object,
// Do the right check and compute the holder register. // Do the right check and compute the holder register.
Register reg = 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); GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
// Check that the function really is a function. // Check that the function really is a function.
...@@ -546,6 +583,7 @@ Object* CallStubCompiler::CompileCallField(Object* object, ...@@ -546,6 +583,7 @@ Object* CallStubCompiler::CompileCallField(Object* object,
Object* CallStubCompiler::CompileCallConstant(Object* object, Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function, JSFunction* function,
String* name,
CheckType check) { CheckType check) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- lr: return address // -- lr: return address
...@@ -569,7 +607,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -569,7 +607,7 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
switch (check) { switch (check) {
case RECEIVER_MAP_CHECK: case RECEIVER_MAP_CHECK:
// Check that the maps haven't changed. // 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 // Patch the receiver on the stack with the global proxy if
// necessary. // necessary.
...@@ -587,8 +625,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -587,8 +625,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX, Context::STRING_FUNCTION_INDEX,
r2); r2);
__ CheckMaps(JSObject::cast(object->GetPrototype()), CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3,
r2, holder, r3, r1, &miss); r1, name, &miss);
break; break;
case NUMBER_CHECK: { case NUMBER_CHECK: {
...@@ -603,8 +641,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -603,8 +641,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::NUMBER_FUNCTION_INDEX, Context::NUMBER_FUNCTION_INDEX,
r2); r2);
__ CheckMaps(JSObject::cast(object->GetPrototype()), CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3,
r2, holder, r3, r1, &miss); r1, name, &miss);
break; break;
} }
...@@ -620,13 +658,13 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -620,13 +658,13 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::BOOLEAN_FUNCTION_INDEX, Context::BOOLEAN_FUNCTION_INDEX,
r2); r2);
__ CheckMaps(JSObject::cast(object->GetPrototype()), CheckPrototypes(JSObject::cast(object->GetPrototype()), r2, holder, r3,
r2, holder, r3, r1, &miss); r1, name, &miss);
break; break;
} }
case JSARRAY_HAS_FAST_ELEMENTS_CHECK: 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() // Make sure object->elements()->map() != Heap::hash_table_map()
// Get the elements array of the object. // Get the elements array of the object.
__ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset)); __ ldr(r3, FieldMemOperand(r1, JSObject::kElementsOffset));
...@@ -712,7 +750,7 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, ...@@ -712,7 +750,7 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
} }
// Check that the maps haven't changed. // 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. // Get the value from the cell.
__ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
...@@ -941,7 +979,7 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object, ...@@ -941,7 +979,7 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
__ ldr(r0, MemOperand(sp, 0)); __ 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); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -962,7 +1000,7 @@ Object* LoadStubCompiler::CompileLoadCallback(JSObject* object, ...@@ -962,7 +1000,7 @@ Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
Label miss; Label miss;
__ ldr(r0, MemOperand(sp, 0)); __ 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); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -984,7 +1022,7 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, ...@@ -984,7 +1022,7 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
__ ldr(r0, MemOperand(sp, 0)); __ 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); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -1005,14 +1043,14 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object, ...@@ -1005,14 +1043,14 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* object,
__ ldr(r0, MemOperand(sp, 0)); __ ldr(r0, MemOperand(sp, 0));
GenerateLoadInterceptor(masm(), GenerateLoadInterceptor(object,
object,
holder, holder,
holder->InterceptorPropertyLookupHint(name), holder->InterceptorPropertyLookupHint(name),
r0, r0,
r2, r2,
r3, r3,
r1, r1,
name,
&miss); &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -1048,7 +1086,7 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, ...@@ -1048,7 +1086,7 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
} }
// Check that the map of the global has not changed. // 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. // Get the value from the cell.
__ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
...@@ -1091,7 +1129,7 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name, ...@@ -1091,7 +1129,7 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
__ cmp(r2, Operand(Handle<String>(name))); __ cmp(r2, Operand(Handle<String>(name)));
__ b(ne, &miss); __ b(ne, &miss);
GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss); GenerateLoadField(receiver, holder, r0, r3, r1, index, name, &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
...@@ -1116,8 +1154,7 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, ...@@ -1116,8 +1154,7 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
__ cmp(r2, Operand(Handle<String>(name))); __ cmp(r2, Operand(Handle<String>(name)));
__ b(ne, &miss); __ b(ne, &miss);
GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3, GenerateLoadCallback(receiver, holder, r0, r2, r3, r1, callback, name, &miss);
r1, callback, &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
...@@ -1143,7 +1180,7 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, ...@@ -1143,7 +1180,7 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
__ cmp(r2, Operand(Handle<String>(name))); __ cmp(r2, Operand(Handle<String>(name)));
__ b(ne, &miss); __ b(ne, &miss);
GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss); GenerateLoadConstant(receiver, holder, r0, r3, r1, value, name, &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
...@@ -1169,14 +1206,14 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, ...@@ -1169,14 +1206,14 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ cmp(r2, Operand(Handle<String>(name))); __ cmp(r2, Operand(Handle<String>(name)));
__ b(ne, &miss); __ b(ne, &miss);
GenerateLoadInterceptor(masm(), GenerateLoadInterceptor(receiver,
receiver,
holder, holder,
Smi::FromInt(JSObject::kLookupInHolder), Smi::FromInt(JSObject::kLookupInHolder),
r0, r0,
r2, r2,
r3, r3,
r1, r1,
name,
&miss); &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
......
...@@ -273,114 +273,6 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, ...@@ -273,114 +273,6 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm,
} }
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) { void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
...@@ -474,10 +366,159 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm, ...@@ -474,10 +366,159 @@ void StubCompiler::GenerateStoreField(MacroAssembler* masm,
#undef __ #undef __
#define __ ACCESS_MASM(masm()) #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 // TODO(1241006): Avoid having lazy compile stubs specialized by the
// number of arguments. It is not needed anymore. // number of arguments. It is not needed anymore.
Object* StubCompiler::CompileLazyCompile(Code::Flags flags) { Object* StubCompiler::CompileLazyCompile(Code::Flags flags) {
...@@ -520,7 +561,8 @@ Object* CallStubCompiler::CompileCallField(Object* object, ...@@ -520,7 +561,8 @@ Object* CallStubCompiler::CompileCallField(Object* object,
// Do the right check and compute the holder register. // Do the right check and compute the holder register.
Register reg = 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); GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
...@@ -553,6 +595,7 @@ Object* CallStubCompiler::CompileCallField(Object* object, ...@@ -553,6 +595,7 @@ Object* CallStubCompiler::CompileCallField(Object* object,
Object* CallStubCompiler::CompileCallConstant(Object* object, Object* CallStubCompiler::CompileCallConstant(Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function, JSFunction* function,
String* name,
CheckType check) { CheckType check) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// ----------------------------------- // -----------------------------------
...@@ -575,7 +618,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -575,7 +618,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
switch (check) { switch (check) {
case RECEIVER_MAP_CHECK: case RECEIVER_MAP_CHECK:
// Check that the maps haven't changed. // 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 // Patch the receiver on the stack with the global proxy if
// necessary. // necessary.
...@@ -595,8 +639,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -595,8 +639,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::STRING_FUNCTION_INDEX, Context::STRING_FUNCTION_INDEX,
ecx); ecx);
__ CheckMaps(JSObject::cast(object->GetPrototype()), CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
ecx, holder, ebx, edx, &miss); ebx, edx, name, &miss);
break; break;
case NUMBER_CHECK: { case NUMBER_CHECK: {
...@@ -611,8 +655,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -611,8 +655,8 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::NUMBER_FUNCTION_INDEX, Context::NUMBER_FUNCTION_INDEX,
ecx); ecx);
__ CheckMaps(JSObject::cast(object->GetPrototype()), CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
ecx, holder, ebx, edx, &miss); ebx, edx, name, &miss);
break; break;
} }
...@@ -628,13 +672,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object, ...@@ -628,13 +672,14 @@ Object* CallStubCompiler::CompileCallConstant(Object* object,
GenerateLoadGlobalFunctionPrototype(masm(), GenerateLoadGlobalFunctionPrototype(masm(),
Context::BOOLEAN_FUNCTION_INDEX, Context::BOOLEAN_FUNCTION_INDEX,
ecx); ecx);
__ CheckMaps(JSObject::cast(object->GetPrototype()), CheckPrototypes(JSObject::cast(object->GetPrototype()), ecx, holder,
ecx, holder, ebx, edx, &miss); ebx, edx, name, &miss);
break; break;
} }
case JSARRAY_HAS_FAST_ELEMENTS_CHECK: 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() // Make sure object->elements()->map() != Heap::dictionary_array_map()
// Get the elements array of the object. // Get the elements array of the object.
__ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
...@@ -692,7 +737,8 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object, ...@@ -692,7 +737,8 @@ Object* CallStubCompiler::CompileCallInterceptor(Object* object,
// Check that maps have not changed and compute the holder register. // Check that maps have not changed and compute the holder register.
Register reg = 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. // Enter an internal frame.
__ EnterInternalFrame(); __ EnterInternalFrame();
...@@ -771,7 +817,7 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object, ...@@ -771,7 +817,7 @@ Object* CallStubCompiler::CompileCallGlobal(JSObject* object,
} }
// Check that the maps haven't changed. // 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. // Get the value from the cell.
__ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell)));
...@@ -1033,6 +1079,7 @@ Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, ...@@ -1033,6 +1079,7 @@ Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
} }
Object* LoadStubCompiler::CompileLoadField(JSObject* object, Object* LoadStubCompiler::CompileLoadField(JSObject* object,
JSObject* holder, JSObject* holder,
int index, int index,
...@@ -1045,7 +1092,7 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object, ...@@ -1045,7 +1092,7 @@ Object* LoadStubCompiler::CompileLoadField(JSObject* object,
Label miss; Label miss;
__ mov(eax, (Operand(esp, kPointerSize))); __ 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); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -1066,8 +1113,8 @@ Object* LoadStubCompiler::CompileLoadCallback(JSObject* object, ...@@ -1066,8 +1113,8 @@ Object* LoadStubCompiler::CompileLoadCallback(JSObject* object,
Label miss; Label miss;
__ mov(eax, (Operand(esp, kPointerSize))); __ mov(eax, (Operand(esp, kPointerSize)));
GenerateLoadCallback(masm(), object, holder, eax, ecx, ebx, GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
edx, callback, &miss); callback, name, &miss);
__ bind(&miss); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -1088,7 +1135,7 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object, ...@@ -1088,7 +1135,7 @@ Object* LoadStubCompiler::CompileLoadConstant(JSObject* object,
Label miss; Label miss;
__ mov(eax, (Operand(esp, kPointerSize))); __ 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); __ bind(&miss);
GenerateLoadMiss(masm(), Code::LOAD_IC); GenerateLoadMiss(masm(), Code::LOAD_IC);
...@@ -1110,14 +1157,14 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, ...@@ -1110,14 +1157,14 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ mov(eax, (Operand(esp, kPointerSize))); __ mov(eax, (Operand(esp, kPointerSize)));
// TODO(368): Compile in the whole chain: all the interceptors in // TODO(368): Compile in the whole chain: all the interceptors in
// prototypes and ultimate answer. // prototypes and ultimate answer.
GenerateLoadInterceptor(masm(), GenerateLoadInterceptor(receiver,
receiver,
holder, holder,
holder->InterceptorPropertyLookupHint(name), holder->InterceptorPropertyLookupHint(name),
eax, eax,
ecx, ecx,
edx, edx,
ebx, ebx,
name,
&miss); &miss);
__ bind(&miss); __ bind(&miss);
...@@ -1154,7 +1201,7 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object, ...@@ -1154,7 +1201,7 @@ Object* LoadStubCompiler::CompileLoadGlobal(JSObject* object,
} }
// Check that the maps haven't changed. // 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. // Get the value from the cell.
__ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell))); __ mov(eax, Immediate(Handle<JSGlobalPropertyCell>(cell)));
...@@ -1200,7 +1247,8 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name, ...@@ -1200,7 +1247,8 @@ Object* KeyedLoadStubCompiler::CompileLoadField(String* name,
__ cmp(Operand(eax), Immediate(Handle<String>(name))); __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss, not_taken); __ 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); __ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_field, 1); __ DecrementCounter(&Counters::keyed_load_field, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
...@@ -1229,8 +1277,8 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name, ...@@ -1229,8 +1277,8 @@ Object* KeyedLoadStubCompiler::CompileLoadCallback(String* name,
__ cmp(Operand(eax), Immediate(Handle<String>(name))); __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss, not_taken); __ j(not_equal, &miss, not_taken);
GenerateLoadCallback(masm(), receiver, holder, ecx, eax, ebx, edx, GenerateLoadCallback(receiver, holder, ecx, eax, ebx, edx,
callback, &miss); callback, name, &miss);
__ bind(&miss); __ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_callback, 1); __ DecrementCounter(&Counters::keyed_load_callback, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
...@@ -1259,7 +1307,8 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name, ...@@ -1259,7 +1307,8 @@ Object* KeyedLoadStubCompiler::CompileLoadConstant(String* name,
__ cmp(Operand(eax), Immediate(Handle<String>(name))); __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss, not_taken); __ 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); __ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_constant_function, 1); __ DecrementCounter(&Counters::keyed_load_constant_function, 1);
GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
...@@ -1287,14 +1336,14 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver, ...@@ -1287,14 +1336,14 @@ Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
__ cmp(Operand(eax), Immediate(Handle<String>(name))); __ cmp(Operand(eax), Immediate(Handle<String>(name)));
__ j(not_equal, &miss, not_taken); __ j(not_equal, &miss, not_taken);
GenerateLoadInterceptor(masm(), GenerateLoadInterceptor(receiver,
receiver,
holder, holder,
Smi::FromInt(JSObject::kLookupInHolder), Smi::FromInt(JSObject::kLookupInHolder),
ecx, ecx,
eax, eax,
edx, edx,
ebx, ebx,
name,
&miss); &miss);
__ bind(&miss); __ bind(&miss);
__ DecrementCounter(&Counters::keyed_load_interceptor, 1); __ DecrementCounter(&Counters::keyed_load_interceptor, 1);
......
...@@ -2653,7 +2653,7 @@ void Dictionary<Shape, Key>::SetEntry(int entry, ...@@ -2653,7 +2653,7 @@ void Dictionary<Shape, Key>::SetEntry(int entry,
Object* key, Object* key,
Object* value, Object* value,
PropertyDetails details) { PropertyDetails details) {
ASSERT(!key->IsString() || details.index() > 0); ASSERT(!key->IsString() || details.IsDeleted() || details.index() > 0);
int index = HashTable<Shape, Key>::EntryToIndex(entry); int index = HashTable<Shape, Key>::EntryToIndex(entry);
WriteBarrierMode mode = FixedArray::GetWriteBarrierMode(); WriteBarrierMode mode = FixedArray::GetWriteBarrierMode();
FixedArray::set(index, key, mode); FixedArray::set(index, key, mode);
......
...@@ -436,8 +436,7 @@ Object* JSObject::SetNormalizedProperty(String* name, ...@@ -436,8 +436,7 @@ Object* JSObject::SetNormalizedProperty(String* name,
store_value = Heap::AllocateJSGlobalPropertyCell(value); store_value = Heap::AllocateJSGlobalPropertyCell(value);
if (store_value->IsFailure()) return store_value; if (store_value->IsFailure()) return store_value;
} }
Object* dict = Object* dict = property_dictionary()->Add(name, store_value, details);
property_dictionary()->Add(name, store_value, details);
if (dict->IsFailure()) return dict; if (dict->IsFailure()) return dict;
set_properties(StringDictionary::cast(dict)); set_properties(StringDictionary::cast(dict));
return value; return value;
...@@ -1712,30 +1711,24 @@ void JSObject::LocalLookupRealNamedProperty(String* name, ...@@ -1712,30 +1711,24 @@ void JSObject::LocalLookupRealNamedProperty(String* name,
} else { } else {
int entry = property_dictionary()->FindEntry(name); int entry = property_dictionary()->FindEntry(name);
if (entry != StringDictionary::kNotFound) { if (entry != StringDictionary::kNotFound) {
// Make sure to disallow caching for uninitialized constants
// found in the dictionary-mode objects.
Object* value = property_dictionary()->ValueAt(entry); Object* value = property_dictionary()->ValueAt(entry);
if (IsGlobalObject()) { if (IsGlobalObject()) {
PropertyDetails d = property_dictionary()->DetailsAt(entry); PropertyDetails d = property_dictionary()->DetailsAt(entry);
if (d.IsDeleted()) { 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(); result->NotFound();
return; return;
} }
value = JSGlobalPropertyCell::cast(value)->value(); value = JSGlobalPropertyCell::cast(value)->value();
ASSERT(result->IsLoaded()); ASSERT(result->IsLoaded());
} }
if (value->IsTheHole()) { // Make sure to disallow caching for uninitialized constants
result->DisallowCaching(); // found in the dictionary-mode objects.
} if (value->IsTheHole()) result->DisallowCaching();
result->DictionaryResult(this, entry); result->DictionaryResult(this, entry);
return; return;
} }
// Slow case object skipped during lookup. Do not use inline caching. // Slow case object skipped during lookup. Do not use inline caching.
result->DisallowCaching(); if (!IsGlobalObject()) result->DisallowCaching();
} }
result->NotFound(); result->NotFound();
} }
...@@ -6841,6 +6834,26 @@ Object* GlobalObject::GetPropertyCell(LookupResult* result) { ...@@ -6841,6 +6834,26 @@ Object* GlobalObject::GetPropertyCell(LookupResult* result) {
} }
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) { Object* SymbolTable::LookupString(String* string, Object** s) {
SymbolKey key(string); SymbolKey key(string);
return LookupKey(&key, s); return LookupKey(&key, s);
...@@ -7200,7 +7213,7 @@ Object* Dictionary<Shape, Key>::AddEntry(Key key, ...@@ -7200,7 +7213,7 @@ Object* Dictionary<Shape, Key>::AddEntry(Key key,
uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash); uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
// Insert element at empty or deleted entry // 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 // Assign an enumeration index to the property and update
// SetNextEnumerationIndex. // SetNextEnumerationIndex.
int index = NextEnumerationIndex(); int index = NextEnumerationIndex();
...@@ -7273,7 +7286,9 @@ int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes( ...@@ -7273,7 +7286,9 @@ int Dictionary<Shape, Key>::NumberOfElementsFilterAttributes(
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i); Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) { 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++; if ((attr & filter) == 0) result++;
} }
} }
...@@ -7297,7 +7312,9 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage, ...@@ -7297,7 +7312,9 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage,
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i); Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) { 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); if ((attr & filter) == 0) storage->set(index++, k);
} }
} }
...@@ -7315,7 +7332,7 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage, ...@@ -7315,7 +7332,7 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
Object* k = KeyAt(i); Object* k = KeyAt(i);
if (IsKey(k)) { if (IsKey(k)) {
PropertyDetails details = DetailsAt(i); PropertyDetails details = DetailsAt(i);
if (!details.IsDontEnum()) { if (details.IsDeleted() || details.IsDontEnum()) continue;
storage->set(index, k); storage->set(index, k);
sort_array->set(index, sort_array->set(index,
Smi::FromInt(details.index()), Smi::FromInt(details.index()),
...@@ -7323,7 +7340,6 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage, ...@@ -7323,7 +7340,6 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
index++; index++;
} }
} }
}
storage->SortPairs(sort_array, sort_array->length()); storage->SortPairs(sort_array, sort_array->length());
ASSERT(storage->length() >= index); ASSERT(storage->length() >= index);
} }
...@@ -7338,6 +7354,8 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) { ...@@ -7338,6 +7354,8 @@ void Dictionary<Shape, Key>::CopyKeysTo(FixedArray* storage) {
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
Object* k = HashTable<Shape, Key>::KeyAt(i); Object* k = HashTable<Shape, Key>::KeyAt(i);
if (HashTable<Shape, Key>::IsKey(k)) { if (HashTable<Shape, Key>::IsKey(k)) {
PropertyDetails details = DetailsAt(i);
if (details.IsDeleted()) continue;
storage->set(index++, k); storage->set(index++, k);
} }
} }
......
...@@ -3240,6 +3240,9 @@ class GlobalObject: public JSObject { ...@@ -3240,6 +3240,9 @@ class GlobalObject: public JSObject {
// Retrieve the property cell used to store a property. // Retrieve the property cell used to store a property.
Object* GetPropertyCell(LookupResult* result); Object* GetPropertyCell(LookupResult* result);
// Ensure that the global object has a cell for the given property name.
Object* EnsurePropertyCell(String* name);
// Casting. // Casting.
static inline GlobalObject* cast(Object* obj); static inline GlobalObject* cast(Object* obj);
......
...@@ -450,7 +450,7 @@ Object* StubCache::ComputeCallConstant(int argc, ...@@ -450,7 +450,7 @@ Object* StubCache::ComputeCallConstant(int argc,
if (!function->is_compiled()) return Failure::InternalError(); if (!function->is_compiled()) return Failure::InternalError();
// Compile the stub - only create stubs for fully compiled functions. // Compile the stub - only create stubs for fully compiled functions.
CallStubCompiler compiler(argc, in_loop); 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; if (code->IsFailure()) return code;
ASSERT_EQ(flags, Code::cast(code)->flags()); ASSERT_EQ(flags, Code::cast(code)->flags());
LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name)); LOG(CodeCreateEvent(Logger::CALL_IC_TAG, Code::cast(code), name));
...@@ -957,6 +957,10 @@ Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { ...@@ -957,6 +957,10 @@ Object* StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) {
Object* StubCompiler::GetCodeWithFlags(Code::Flags flags, const char* name) { 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; CodeDesc desc;
masm_.GetCode(&desc); masm_.GetCode(&desc);
Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject()); Object* result = Heap::CreateCode(desc, NULL, flags, masm_.CodeObject());
......
...@@ -324,7 +324,7 @@ class StubCompiler BASE_EMBEDDED { ...@@ -324,7 +324,7 @@ class StubCompiler BASE_EMBEDDED {
JSARRAY_HAS_FAST_ELEMENTS_CHECK JSARRAY_HAS_FAST_ELEMENTS_CHECK
}; };
StubCompiler() : scope_(), masm_(NULL, 256) { } StubCompiler() : scope_(), masm_(NULL, 256), failure_(NULL) { }
Object* CompileCallInitialize(Code::Flags flags); Object* CompileCallInitialize(Code::Flags flags);
Object* CompileCallPreMonomorphic(Code::Flags flags); Object* CompileCallPreMonomorphic(Code::Flags flags);
...@@ -344,40 +344,7 @@ class StubCompiler BASE_EMBEDDED { ...@@ -344,40 +344,7 @@ class StubCompiler BASE_EMBEDDED {
static void GenerateFastPropertyLoad(MacroAssembler* masm, static void GenerateFastPropertyLoad(MacroAssembler* masm,
Register dst, Register src, Register dst, Register src,
JSObject* holder, int index); 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, static void GenerateLoadArrayLength(MacroAssembler* masm,
Register receiver, Register receiver,
Register scratch, Register scratch,
...@@ -412,10 +379,60 @@ class StubCompiler BASE_EMBEDDED { ...@@ -412,10 +379,60 @@ class StubCompiler BASE_EMBEDDED {
Object* GetCodeWithFlags(Code::Flags flags, String* name); Object* GetCodeWithFlags(Code::Flags flags, String* name);
MacroAssembler* masm() { return &masm_; } 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: private:
HandleScope scope_; HandleScope scope_;
MacroAssembler masm_; MacroAssembler masm_;
Failure* failure_;
}; };
...@@ -518,6 +535,7 @@ class CallStubCompiler: public StubCompiler { ...@@ -518,6 +535,7 @@ class CallStubCompiler: public StubCompiler {
Object* CompileCallConstant(Object* object, Object* CompileCallConstant(Object* object,
JSObject* holder, JSObject* holder,
JSFunction* function, JSFunction* function,
String* name,
CheckType check); CheckType check);
Object* CompileCallInterceptor(Object* object, Object* CompileCallInterceptor(Object* object,
JSObject* holder, JSObject* holder,
......
...@@ -42,7 +42,8 @@ namespace internal { ...@@ -42,7 +42,8 @@ namespace internal {
Object* CallStubCompiler::CompileCallConstant(Object* a, Object* CallStubCompiler::CompileCallConstant(Object* a,
JSObject* b, JSObject* b,
JSFunction* c, JSFunction* c,
StubCompiler::CheckType d) { String* d,
StubCompiler::CheckType e) {
UNIMPLEMENTED(); UNIMPLEMENTED();
return NULL; return NULL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment