Turn Load/StoreGlobal into a handler.
BUG= R=ulan@chromium.org Review URL: https://chromiumcodereview.appspot.com/26968004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@17550 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
e7ef18110d
commit
442e77d536
@ -3020,10 +3020,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
||||
bool is_dont_delete) {
|
||||
Label success, miss;
|
||||
|
||||
__ CheckMap(
|
||||
receiver(), scratch1(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK);
|
||||
HandlerFrontendHeader(
|
||||
object, receiver(), Handle<JSObject>::cast(global), name, &miss);
|
||||
HandlerFrontendHeader(object, receiver(), global, name, &miss);
|
||||
|
||||
// Get the value from the cell.
|
||||
__ mov(r3, Operand(cell));
|
||||
@ -3045,7 +3042,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
||||
__ Ret();
|
||||
|
||||
// Return the generated code.
|
||||
return GetICCode(kind(), Code::NORMAL, name);
|
||||
return GetCode(kind(), Code::NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
|
109
src/code-stubs.h
109
src/code-stubs.h
@ -553,51 +553,6 @@ class FastNewBlockContextStub : public PlatformCodeStub {
|
||||
int MinorKey() { return slots_; }
|
||||
};
|
||||
|
||||
class StoreGlobalStub : public HydrogenCodeStub {
|
||||
public:
|
||||
StoreGlobalStub(StrictModeFlag strict_mode, bool is_constant) {
|
||||
bit_field_ = StrictModeBits::encode(strict_mode) |
|
||||
IsConstantBits::encode(is_constant);
|
||||
}
|
||||
|
||||
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
||||
|
||||
virtual void InitializeInterfaceDescriptor(
|
||||
Isolate* isolate,
|
||||
CodeStubInterfaceDescriptor* descriptor);
|
||||
|
||||
virtual Code::Kind GetCodeKind() const { return Code::STORE_IC; }
|
||||
virtual InlineCacheState GetICState() { return MONOMORPHIC; }
|
||||
virtual Code::ExtraICState GetExtraICState() { return bit_field_; }
|
||||
|
||||
bool is_constant() {
|
||||
return IsConstantBits::decode(bit_field_);
|
||||
}
|
||||
void set_is_constant(bool value) {
|
||||
bit_field_ = IsConstantBits::update(bit_field_, value);
|
||||
}
|
||||
|
||||
Representation representation() {
|
||||
return Representation::FromKind(RepresentationBits::decode(bit_field_));
|
||||
}
|
||||
void set_representation(Representation r) {
|
||||
bit_field_ = RepresentationBits::update(bit_field_, r.kind());
|
||||
}
|
||||
|
||||
private:
|
||||
virtual int NotMissMinorKey() { return GetExtraICState(); }
|
||||
Major MajorKey() { return StoreGlobal; }
|
||||
|
||||
class StrictModeBits: public BitField<StrictModeFlag, 0, 1> {};
|
||||
class IsConstantBits: public BitField<bool, 1, 1> {};
|
||||
class RepresentationBits: public BitField<Representation::Kind, 2, 8> {};
|
||||
|
||||
int bit_field_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
|
||||
};
|
||||
|
||||
|
||||
class FastCloneShallowArrayStub : public HydrogenCodeStub {
|
||||
public:
|
||||
// Maximum length of copied elements array.
|
||||
@ -899,7 +854,6 @@ class HICStub: public HydrogenCodeStub {
|
||||
virtual InlineCacheState GetICState() { return MONOMORPHIC; }
|
||||
|
||||
protected:
|
||||
HICStub() { }
|
||||
class KindBits: public BitField<Code::Kind, 0, 4> {};
|
||||
virtual Code::Kind kind() const = 0;
|
||||
};
|
||||
@ -909,16 +863,12 @@ class HandlerStub: public HICStub {
|
||||
public:
|
||||
virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
|
||||
virtual int GetStubFlags() { return kind(); }
|
||||
|
||||
protected:
|
||||
HandlerStub() : HICStub() { }
|
||||
};
|
||||
|
||||
|
||||
class LoadFieldStub: public HandlerStub {
|
||||
public:
|
||||
LoadFieldStub(bool inobject, int index, Representation representation)
|
||||
: HandlerStub() {
|
||||
LoadFieldStub(bool inobject, int index, Representation representation) {
|
||||
Initialize(Code::LOAD_IC, inobject, index, representation);
|
||||
}
|
||||
|
||||
@ -980,6 +930,63 @@ class LoadFieldStub: public HandlerStub {
|
||||
};
|
||||
|
||||
|
||||
class StoreGlobalStub : public HandlerStub {
|
||||
public:
|
||||
StoreGlobalStub(StrictModeFlag strict_mode, bool is_constant) {
|
||||
bit_field_ = StrictModeBits::encode(strict_mode) |
|
||||
IsConstantBits::encode(is_constant);
|
||||
}
|
||||
|
||||
Handle<Code> GetCodeCopyFromTemplate(Isolate* isolate,
|
||||
Map* receiver_map,
|
||||
PropertyCell* cell) {
|
||||
Handle<Code> code = CodeStub::GetCodeCopyFromTemplate(isolate);
|
||||
// Replace the placeholder cell and global object map with the actual global
|
||||
// cell and receiver map.
|
||||
Map* cell_map = isolate->heap()->global_property_cell_map();
|
||||
code->ReplaceNthObject(1, cell_map, cell);
|
||||
code->ReplaceNthObject(1, isolate->heap()->meta_map(), receiver_map);
|
||||
return code;
|
||||
}
|
||||
|
||||
virtual Code::Kind kind() const { return Code::STORE_IC; }
|
||||
|
||||
virtual Handle<Code> GenerateCode(Isolate* isolate);
|
||||
|
||||
virtual void InitializeInterfaceDescriptor(
|
||||
Isolate* isolate,
|
||||
CodeStubInterfaceDescriptor* descriptor);
|
||||
|
||||
virtual Code::ExtraICState GetExtraICState() { return bit_field_; }
|
||||
|
||||
bool is_constant() {
|
||||
return IsConstantBits::decode(bit_field_);
|
||||
}
|
||||
void set_is_constant(bool value) {
|
||||
bit_field_ = IsConstantBits::update(bit_field_, value);
|
||||
}
|
||||
|
||||
Representation representation() {
|
||||
return Representation::FromKind(RepresentationBits::decode(bit_field_));
|
||||
}
|
||||
void set_representation(Representation r) {
|
||||
bit_field_ = RepresentationBits::update(bit_field_, r.kind());
|
||||
}
|
||||
|
||||
private:
|
||||
virtual int NotMissMinorKey() { return GetExtraICState(); }
|
||||
Major MajorKey() { return StoreGlobal; }
|
||||
|
||||
class StrictModeBits: public BitField<StrictModeFlag, 0, 1> {};
|
||||
class IsConstantBits: public BitField<bool, 1, 1> {};
|
||||
class RepresentationBits: public BitField<Representation::Kind, 2, 8> {};
|
||||
|
||||
int bit_field_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(StoreGlobalStub);
|
||||
};
|
||||
|
||||
|
||||
class KeyedLoadFieldStub: public LoadFieldStub {
|
||||
public:
|
||||
KeyedLoadFieldStub(bool inobject, int index, Representation representation)
|
||||
|
@ -3125,9 +3125,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
||||
bool is_dont_delete) {
|
||||
Label success, miss;
|
||||
|
||||
__ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK);
|
||||
HandlerFrontendHeader(
|
||||
object, receiver(), Handle<JSObject>::cast(global), name, &miss);
|
||||
HandlerFrontendHeader(object, receiver(), global, name, &miss);
|
||||
// Get the value from the cell.
|
||||
if (Serializer::enabled()) {
|
||||
__ mov(eax, Immediate(cell));
|
||||
@ -3154,7 +3152,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
||||
__ ret(0);
|
||||
|
||||
// Return the generated code.
|
||||
return GetICCode(kind(), Code::NORMAL, name);
|
||||
return GetCode(kind(), Code::NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
|
41
src/ic.cc
41
src/ic.cc
@ -768,12 +768,13 @@ void CallICBase::UpdateCaches(LookupResult* lookup,
|
||||
// Bail out if we didn't find a result.
|
||||
if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
|
||||
|
||||
// Compute the number of arguments.
|
||||
Handle<Code> code;
|
||||
code = state() == UNINITIALIZED
|
||||
? pre_monomorphic_stub()
|
||||
: ComputeMonomorphicStub(lookup, object, name);
|
||||
if (state() == UNINITIALIZED) {
|
||||
set_target(*pre_monomorphic_stub());
|
||||
TRACE_IC("CallIC", name);
|
||||
return;
|
||||
}
|
||||
|
||||
Handle<Code> code = ComputeMonomorphicStub(lookup, object, name);
|
||||
// If there's no appropriate stub we simply avoid updating the caches.
|
||||
// TODO(verwaest): Install a slow fallback in this case to avoid not learning,
|
||||
// and deopting Crankshaft code.
|
||||
@ -954,7 +955,6 @@ bool IC::UpdatePolymorphicIC(Handle<HeapObject> receiver,
|
||||
Handle<String> name,
|
||||
Handle<Code> code) {
|
||||
if (!code->is_handler()) return false;
|
||||
|
||||
MapHandleList receiver_maps;
|
||||
CodeHandleList handlers;
|
||||
|
||||
@ -1133,7 +1133,9 @@ void LoadIC::UpdateCaches(LookupResult* lookup,
|
||||
// This is the first time we execute this inline cache.
|
||||
// Set the target to the pre monomorphic stub to delay
|
||||
// setting the monomorphic state.
|
||||
code = pre_monomorphic_stub();
|
||||
set_target(*pre_monomorphic_stub());
|
||||
TRACE_IC("LoadIC", name);
|
||||
return;
|
||||
} else if (!lookup->IsCacheable()) {
|
||||
// Bail out if the result is not cacheable.
|
||||
code = slow_stub();
|
||||
@ -1175,8 +1177,9 @@ Handle<Code> IC::ComputeHandler(LookupResult* lookup,
|
||||
if (!code.is_null()) return code;
|
||||
|
||||
code = CompileHandler(lookup, receiver, name, value);
|
||||
ASSERT(code->is_handler());
|
||||
|
||||
if (code->is_handler() && code->type() != Code::NORMAL) {
|
||||
if (code->type() != Code::NORMAL) {
|
||||
HeapObject::UpdateMapCodeCache(receiver, name, code);
|
||||
}
|
||||
|
||||
@ -1215,9 +1218,11 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
|
||||
Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
|
||||
Handle<PropertyCell> cell(
|
||||
global->GetPropertyCell(lookup), isolate());
|
||||
// TODO(verwaest): Turn into a handler.
|
||||
return isolate()->stub_cache()->ComputeLoadGlobal(
|
||||
name, receiver, global, cell, lookup->IsDontDelete());
|
||||
Handle<Code> code = compiler.CompileLoadGlobal(
|
||||
receiver, global, cell, name, lookup->IsDontDelete());
|
||||
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
|
||||
HeapObject::UpdateMapCodeCache(receiver, name, code);
|
||||
return code;
|
||||
}
|
||||
// There is only one shared stub for loading normalized
|
||||
// properties. It does not traverse the prototype chain, so the
|
||||
@ -1632,11 +1637,15 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
|
||||
// from the property cell. So the property must be directly on the
|
||||
// global object.
|
||||
Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
|
||||
Handle<PropertyCell> cell(
|
||||
global->GetPropertyCell(lookup), isolate());
|
||||
// TODO(verwaest): Turn into a handler.
|
||||
return isolate()->stub_cache()->ComputeStoreGlobal(
|
||||
name, global, cell, value, strict_mode());
|
||||
Handle<PropertyCell> cell(global->GetPropertyCell(lookup), isolate());
|
||||
Handle<Type> union_type = PropertyCell::UpdatedType(cell, value);
|
||||
StoreGlobalStub stub(strict_mode(), union_type->IsConstant());
|
||||
|
||||
Handle<Code> code = stub.GetCodeCopyFromTemplate(
|
||||
isolate(), receiver->map(), *cell);
|
||||
// TODO(verwaest): Move caching of these NORMAL stubs outside as well.
|
||||
HeapObject::UpdateMapCodeCache(receiver, name, code);
|
||||
return code;
|
||||
}
|
||||
ASSERT(holder.is_identical_to(receiver));
|
||||
return strict_mode() == kStrictMode
|
||||
|
@ -10543,7 +10543,7 @@ Map* Code::FindFirstMap() {
|
||||
void Code::ReplaceNthObject(int n,
|
||||
Map* match_map,
|
||||
Object* replace_with) {
|
||||
ASSERT(is_inline_cache_stub());
|
||||
ASSERT(is_inline_cache_stub() || is_handler());
|
||||
DisallowHeapAllocation no_allocation;
|
||||
int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
|
||||
for (RelocIterator it(this, mask); !it.done(); it.next()) {
|
||||
|
@ -202,22 +202,6 @@ Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name,
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeLoadGlobal(Handle<Name> name,
|
||||
Handle<JSObject> receiver,
|
||||
Handle<GlobalObject> holder,
|
||||
Handle<PropertyCell> cell,
|
||||
bool is_dont_delete) {
|
||||
Handle<Code> stub = FindIC(name, receiver, Code::LOAD_IC);
|
||||
if (!stub.is_null()) return stub;
|
||||
|
||||
LoadStubCompiler compiler(isolate_);
|
||||
Handle<Code> ic =
|
||||
compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete);
|
||||
HeapObject::UpdateMapCodeCache(receiver, name, ic);
|
||||
return ic;
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) {
|
||||
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC);
|
||||
Handle<Name> name =
|
||||
@ -262,35 +246,6 @@ Handle<Code> StubCache::ComputeKeyedStoreElement(
|
||||
}
|
||||
|
||||
|
||||
Handle<Code> StubCache::ComputeStoreGlobal(Handle<Name> name,
|
||||
Handle<GlobalObject> receiver,
|
||||
Handle<PropertyCell> cell,
|
||||
Handle<Object> value,
|
||||
StrictModeFlag strict_mode) {
|
||||
Handle<Type> union_type = PropertyCell::UpdatedType(cell, value);
|
||||
bool is_constant = union_type->IsConstant();
|
||||
StoreGlobalStub stub(strict_mode, is_constant);
|
||||
|
||||
Handle<Code> code = FindIC(
|
||||
name, Handle<JSObject>::cast(receiver),
|
||||
Code::STORE_IC, stub.GetExtraICState());
|
||||
if (!code.is_null()) return code;
|
||||
|
||||
// Replace the placeholder cell and global object map with the actual global
|
||||
// cell and receiver map.
|
||||
Handle<Map> meta_map(isolate_->heap()->meta_map());
|
||||
Handle<Object> receiver_map(receiver->map(), isolate_);
|
||||
code = stub.GetCodeCopyFromTemplate(isolate_);
|
||||
code->ReplaceNthObject(1, *meta_map, *receiver_map);
|
||||
Handle<Map> cell_map(isolate_->heap()->global_property_cell_map());
|
||||
code->ReplaceNthObject(1, *cell_map, *cell);
|
||||
|
||||
HeapObject::UpdateMapCodeCache(receiver, name, code);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
||||
#define CALL_LOGGER_TAG(kind, type) \
|
||||
(kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type)
|
||||
|
||||
@ -1596,7 +1551,6 @@ Handle<Code> BaseLoadStoreStubCompiler::GetICCode(Code::Kind kind,
|
||||
Handle<Code> BaseLoadStoreStubCompiler::GetCode(Code::Kind kind,
|
||||
Code::StubType type,
|
||||
Handle<Name> name) {
|
||||
ASSERT(type != Code::NORMAL);
|
||||
Code::Flags flags = Code::ComputeFlags(
|
||||
Code::HANDLER, MONOMORPHIC, extra_state(), type, kind);
|
||||
Handle<Code> code = GetCodeWithFlags(flags, name);
|
||||
|
@ -105,12 +105,6 @@ class StubCache {
|
||||
Handle<Code> ComputeLoadNonexistent(Handle<Name> name,
|
||||
Handle<JSObject> object);
|
||||
|
||||
Handle<Code> ComputeLoadGlobal(Handle<Name> name,
|
||||
Handle<JSObject> object,
|
||||
Handle<GlobalObject> holder,
|
||||
Handle<PropertyCell> cell,
|
||||
bool is_dont_delete);
|
||||
|
||||
// ---
|
||||
|
||||
Handle<Code> ComputeKeyedLoadField(Handle<Name> name,
|
||||
@ -140,12 +134,6 @@ class StubCache {
|
||||
Handle<JSObject> object,
|
||||
Handle<JSObject> holder);
|
||||
|
||||
Handle<Code> ComputeStoreGlobal(Handle<Name> name,
|
||||
Handle<GlobalObject> object,
|
||||
Handle<PropertyCell> cell,
|
||||
Handle<Object> value,
|
||||
StrictModeFlag strict_mode);
|
||||
|
||||
Handle<Code> ComputeKeyedLoadElement(Handle<Map> receiver_map);
|
||||
|
||||
Handle<Code> ComputeKeyedStoreElement(Handle<Map> receiver_map,
|
||||
|
@ -3036,10 +3036,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
||||
// TODO(verwaest): Directly store to rax. Currently we cannot do this, since
|
||||
// rax is used as receiver(), which we would otherwise clobber before a
|
||||
// potential miss.
|
||||
|
||||
__ CheckMap(receiver(), Handle<Map>(object->map()), &miss, DO_SMI_CHECK);
|
||||
HandlerFrontendHeader(
|
||||
object, receiver(), Handle<JSObject>::cast(global), name, &miss);
|
||||
HandlerFrontendHeader(object, receiver(), global, name, &miss);
|
||||
|
||||
// Get the value from the cell.
|
||||
__ Move(rbx, cell);
|
||||
@ -3063,7 +3060,7 @@ Handle<Code> LoadStubCompiler::CompileLoadGlobal(
|
||||
__ ret(0);
|
||||
|
||||
// Return the generated code.
|
||||
return GetICCode(kind(), Code::NORMAL, name);
|
||||
return GetCode(kind(), Code::NORMAL, name);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user