Handlify upper layers of KeyedLoadIC.

BUG=
TEST=

Review URL: http://codereview.chromium.org/8352003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9714 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
ulan@chromium.org 2011-10-20 09:35:47 +00:00
parent 655b2332d7
commit f985b15aae
6 changed files with 301 additions and 310 deletions

196
src/ic.cc
View File

@ -368,45 +368,6 @@ static bool HasInterceptorGetter(JSObject* object) {
}
static void LookupForRead(Object* object,
String* name,
LookupResult* lookup) {
AssertNoAllocation no_gc;
// Skip all the objects with named interceptors, but
// without actual getter.
while (true) {
object->Lookup(name, lookup);
// Besides normal conditions (property not found or it's not
// an interceptor), bail out if lookup is not cacheable: we won't
// be able to IC it anyway and regular lookup should work fine.
if (!lookup->IsFound()
|| (lookup->type() != INTERCEPTOR)
|| !lookup->IsCacheable()) {
return;
}
JSObject* holder = lookup->holder();
if (HasInterceptorGetter(holder)) {
return;
}
holder->LocalLookupRealNamedProperty(name, lookup);
if (lookup->IsProperty()) {
ASSERT(lookup->type() != INTERCEPTOR);
return;
}
Object* proto = holder->GetPrototype();
if (proto->IsNull()) {
lookup->NotFound();
return;
}
object = proto;
}
}
static void LookupForRead(Handle<Object> object,
Handle<String> name,
LookupResult* lookup) {
@ -1107,9 +1068,8 @@ MaybeObject* KeyedLoadIC::Load(State state,
bool force_generic_stub) {
// Check for values that can be converted into a symbol.
// TODO(1295): Remove this code.
HandleScope scope(isolate());
if (key->IsHeapNumber() &&
isnan(HeapNumber::cast(*key)->value())) {
isnan(Handle<HeapNumber>::cast(key)->value())) {
key = isolate()->factory()->nan_symbol();
} else if (key->IsUndefined()) {
key = isolate()->factory()->undefined_symbol();
@ -1131,13 +1091,11 @@ MaybeObject* KeyedLoadIC::Load(State state,
if (object->IsString() &&
name->Equals(isolate()->heap()->length_symbol())) {
Handle<String> string = Handle<String>::cast(object);
Object* code = NULL;
{ MaybeObject* maybe_code =
isolate()->stub_cache()->ComputeKeyedLoadStringLength(*name,
*string);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code));
Handle<Code> code =
isolate()->stub_cache()->ComputeKeyedLoadStringLength(name,
string);
ASSERT(!code.is_null());
set_target(*code);
#ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target());
#endif // DEBUG
@ -1148,31 +1106,26 @@ MaybeObject* KeyedLoadIC::Load(State state,
if (object->IsJSArray() &&
name->Equals(isolate()->heap()->length_symbol())) {
Handle<JSArray> array = Handle<JSArray>::cast(object);
Object* code;
{ MaybeObject* maybe_code =
isolate()->stub_cache()->ComputeKeyedLoadArrayLength(*name,
*array);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code));
Handle<Code> code =
isolate()->stub_cache()->ComputeKeyedLoadArrayLength(name, array);
ASSERT(!code.is_null());
set_target(*code);
#ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target());
#endif // DEBUG
return JSArray::cast(*object)->length();
return array->length();
}
// Use specialized code for getting prototype of functions.
if (object->IsJSFunction() &&
name->Equals(isolate()->heap()->prototype_symbol()) &&
JSFunction::cast(*object)->should_have_prototype()) {
Handle<JSFunction>::cast(object)->should_have_prototype()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(object);
Object* code;
{ MaybeObject* maybe_code =
isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
*name, *function);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
set_target(Code::cast(code));
Handle<Code> code =
isolate()->stub_cache()->ComputeKeyedLoadFunctionPrototype(
name, function);
ASSERT(!code.is_null());
set_target(*code);
#ifdef DEBUG
TraceIC("KeyedLoadIC", name, state, target());
#endif // DEBUG
@ -1184,15 +1137,14 @@ MaybeObject* KeyedLoadIC::Load(State state,
// the element or char if so.
uint32_t index = 0;
if (name->AsArrayIndex(&index)) {
HandleScope scope(isolate());
// Rewrite to the generic keyed load stub.
if (FLAG_use_ic) set_target(generic_stub());
if (FLAG_use_ic) set_target(*generic_stub());
return Runtime::GetElementOrCharAt(isolate(), object, index);
}
// Named lookup.
LookupResult lookup(isolate());
LookupForRead(*object, *name, &lookup);
LookupForRead(object, name, &lookup);
// If we did not find a property, check if we need to throw an exception.
if (!lookup.IsProperty() && IsContextual(object)) {
@ -1206,17 +1158,15 @@ MaybeObject* KeyedLoadIC::Load(State state,
PropertyAttributes attr;
if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
// Get the property.
Object* result;
{ MaybeObject* maybe_result =
object->GetProperty(*object, &lookup, *name, &attr);
if (!maybe_result->ToObject(&result)) return maybe_result;
}
Handle<Object> result =
Object::GetProperty(object, object, &lookup, name, &attr);
RETURN_IF_EMPTY_HANDLE(isolate(), result);
// If the property is not present, check if we need to throw an
// exception.
if (attr == ABSENT && IsContextual(object)) {
return ReferenceError("not_defined", name);
}
return result;
return *result;
}
return object->GetProperty(*object, &lookup, *name, &attr);
@ -1227,31 +1177,25 @@ MaybeObject* KeyedLoadIC::Load(State state,
bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
if (use_ic) {
Code* stub = generic_stub();
Handle<Code> stub = generic_stub();
if (!force_generic_stub) {
if (object->IsString() && key->IsNumber()) {
if (state == UNINITIALIZED) {
stub = string_stub();
}
} else if (object->IsJSObject()) {
JSObject* receiver = JSObject::cast(*object);
Heap* heap = Handle<JSObject>::cast(object)->GetHeap();
Map* elements_map = Handle<JSObject>::cast(object)->elements()->map();
if (elements_map == heap->non_strict_arguments_elements_map()) {
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
if (receiver->elements()->map() ==
isolate()->heap()->non_strict_arguments_elements_map()) {
stub = non_strict_arguments_stub();
} else if (receiver->HasIndexedInterceptor()) {
stub = indexed_interceptor_stub();
} else if (key->IsSmi() && (target() != non_strict_arguments_stub())) {
MaybeObject* maybe_stub = ComputeStub(receiver,
LOAD,
kNonStrictMode,
stub);
stub = maybe_stub->IsFailure() ?
NULL : Code::cast(maybe_stub->ToObjectUnchecked());
} else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub);
}
}
}
if (stub != NULL) set_target(stub);
if (!stub.is_null()) set_target(*stub);
}
#ifdef DEBUG
@ -1263,8 +1207,10 @@ MaybeObject* KeyedLoadIC::Load(State state,
}
void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
Handle<Object> object, Handle<String> name) {
void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
State state,
Handle<Object> object,
Handle<String> name) {
// Bail out if we didn't find a result.
if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
@ -1274,63 +1220,57 @@ void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
// Compute the code stub for this load.
MaybeObject* maybe_code = NULL;
Object* code;
Handle<Code> code;
if (state == UNINITIALIZED) {
// This is the first time we execute this inline cache.
// Set the target to the pre monomorphic stub to delay
// setting the monomorphic state.
maybe_code = pre_monomorphic_stub();
code = pre_monomorphic_stub();
} else {
// Compute a monomorphic stub.
Handle<JSObject> holder(lookup->holder());
switch (lookup->type()) {
case FIELD: {
maybe_code = isolate()->stub_cache()->ComputeKeyedLoadField(
*name, *receiver, lookup->holder(), lookup->GetFieldIndex());
case FIELD:
code = isolate()->stub_cache()->ComputeKeyedLoadField(
name, receiver, holder, lookup->GetFieldIndex());
break;
}
case CONSTANT_FUNCTION: {
Object* constant = lookup->GetConstantFunction();
maybe_code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
*name, *receiver, lookup->holder(), constant);
Handle<Object> constant(lookup->GetConstantFunction());
code = isolate()->stub_cache()->ComputeKeyedLoadConstant(
name, receiver, holder, constant);
break;
}
case CALLBACKS: {
if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
AccessorInfo* callback =
AccessorInfo::cast(lookup->GetCallbackObject());
Handle<Object> callback_object(lookup->GetCallbackObject());
if (!callback_object->IsAccessorInfo()) return;
Handle<AccessorInfo> callback =
Handle<AccessorInfo>::cast(callback_object);
if (v8::ToCData<Address>(callback->getter()) == 0) return;
maybe_code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
*name, *receiver, lookup->holder(), callback);
code = isolate()->stub_cache()->ComputeKeyedLoadCallback(
name, receiver, holder, callback);
break;
}
case INTERCEPTOR: {
case INTERCEPTOR:
ASSERT(HasInterceptorGetter(lookup->holder()));
maybe_code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
*name, *receiver, lookup->holder());
code = isolate()->stub_cache()->ComputeKeyedLoadInterceptor(
name, receiver, holder);
break;
}
default: {
default:
// Always rewrite to the generic case so that we do not
// repeatedly try to rewrite.
maybe_code = generic_stub();
code = generic_stub();
break;
}
}
}
// If we're unable to compute the stub (not enough memory left), we
// simply avoid updating the caches.
if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
// Patch the call site depending on the state of the cache. Make
// sure to always rewrite from monomorphic to megamorphic.
ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
set_target(Code::cast(code));
set_target(*code);
} else if (state == MONOMORPHIC) {
set_target(megamorphic_stub());
set_target(*megamorphic_stub());
}
#ifdef DEBUG
@ -1566,7 +1506,7 @@ static bool AddOneReceiverMapIfMissing(MapList* receiver_maps,
void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
ASSERT(stub->is_inline_cache_stub());
if (stub == string_stub()) {
if (!string_stub().is_null() && stub == *string_stub()) {
return result->Add(isolate()->heap()->string_map());
} else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
if (stub->ic_state() == MONOMORPHIC) {
@ -1586,6 +1526,20 @@ void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
}
Handle<Code> KeyedIC::ComputeStub(Handle<JSObject> receiver,
StubKind stub_kind,
StrictModeFlag strict_mode,
Handle<Code> generic_stub) {
CALL_HEAP_FUNCTION(isolate(),
ComputeStub(*receiver,
stub_kind,
strict_mode,
*generic_stub),
Code);
}
MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
StubKind stub_kind,
StrictModeFlag strict_mode,
@ -1663,8 +1617,8 @@ MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
Map* receiver_map,
StrictModeFlag strict_mode) {
if ((receiver_map->instance_type() & kNotStringTag) == 0) {
ASSERT(string_stub() != NULL);
return string_stub();
ASSERT(!string_stub().is_null());
return *string_stub();
} else {
ASSERT(receiver_map->has_dictionary_elements() ||
receiver_map->has_fast_elements() ||
@ -1993,7 +1947,7 @@ RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) {
// Used from ic-<arch>.cc
RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
NoHandleAllocation na;
HandleScope scope(isolate);
ASSERT(args.length() == 2);
KeyedLoadIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
@ -2002,7 +1956,7 @@ RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
NoHandleAllocation na;
HandleScope scope(isolate);
ASSERT(args.length() == 2);
KeyedLoadIC ic(isolate);
IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);

View File

@ -356,12 +356,17 @@ class KeyedIC: public IC {
ElementsKind elements_kind) = 0;
protected:
virtual Code* string_stub() {
return NULL;
virtual Handle<Code> string_stub() {
return Handle<Code>::null();
}
virtual Code::Kind kind() const = 0;
Handle<Code> ComputeStub(Handle<JSObject> receiver,
StubKind stub_kind,
StrictModeFlag strict_mode,
Handle<Code> default_stub);
MaybeObject* ComputeStub(JSObject* receiver,
StubKind stub_kind,
StrictModeFlag strict_mode,
@ -433,9 +438,8 @@ class KeyedLoadIC: public KeyedIC {
MapList* receiver_maps,
StrictModeFlag strict_mode);
virtual Code* string_stub() {
return isolate()->builtins()->builtin(
Builtins::kKeyedLoadIC_String);
virtual Handle<Code> string_stub() {
return isolate()->builtins()->KeyedLoadIC_String();
}
private:
@ -450,25 +454,20 @@ class KeyedLoadIC: public KeyedIC {
return Isolate::Current()->builtins()->builtin(
Builtins::kKeyedLoadIC_Initialize);
}
Code* megamorphic_stub() {
return isolate()->builtins()->builtin(
Builtins::kKeyedLoadIC_Generic);
Handle<Code> megamorphic_stub() {
return isolate()->builtins()->KeyedLoadIC_Generic();
}
Code* generic_stub() {
return isolate()->builtins()->builtin(
Builtins::kKeyedLoadIC_Generic);
Handle<Code> generic_stub() {
return isolate()->builtins()->KeyedLoadIC_Generic();
}
Code* pre_monomorphic_stub() {
return isolate()->builtins()->builtin(
Builtins::kKeyedLoadIC_PreMonomorphic);
Handle<Code> pre_monomorphic_stub() {
return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
}
Code* indexed_interceptor_stub() {
return isolate()->builtins()->builtin(
Builtins::kKeyedLoadIC_IndexedInterceptor);
Handle<Code> indexed_interceptor_stub() {
return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
}
Code* non_strict_arguments_stub() {
return isolate()->builtins()->builtin(
Builtins::kKeyedLoadIC_NonStrictArguments);
Handle<Code> non_strict_arguments_stub() {
return isolate()->builtins()->KeyedLoadIC_NonStrictArguments();
}
static void Clear(Address address, Code* target);

View File

@ -4655,6 +4655,13 @@ MaybeObject* Map::CopyDropTransitions() {
return new_map;
}
void Map::UpdateCodeCache(Handle<Map> map,
Handle<String> name,
Handle<Code> code) {
Isolate* isolate = map->GetIsolate();
CALL_HEAP_FUNCTION_VOID(isolate,
map->UpdateCodeCache(*name, *code));
}
MaybeObject* Map::UpdateCodeCache(String* name, Code* code) {
// Allocate the code cache if not present.

View File

@ -4258,6 +4258,9 @@ class Map: public HeapObject {
inline void ClearCodeCache(Heap* heap);
// Update code cache.
static void UpdateCodeCache(Handle<Map> map,
Handle<String> name,
Handle<Code> code);
MUST_USE_RESULT MaybeObject* UpdateCodeCache(String* name, Code* code);
// Returns the found code or undefined if absent.

View File

@ -306,187 +306,193 @@ Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name,
}
MaybeObject* StubCache::ComputeKeyedLoadField(String* name,
JSObject* receiver,
JSObject* holder,
Handle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name,
Handle<JSObject> object,
Handle<JSObject> holder,
int index) {
CALL_HEAP_FUNCTION(isolate(),
CompileLoadField(*name, *object, *holder, index),
Code);
}
Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
int field_index) {
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD);
Object* code = receiver->map()->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
HandleScope scope(isolate_);
KeyedLoadStubCompiler compiler(isolate_);
{ MaybeObject* maybe_code =
compiler.CompileLoadField(name, receiver, holder, field_index);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
PROFILE(isolate_,
CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
Object* result;
{ MaybeObject* maybe_result =
receiver->UpdateMapCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
}
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> code =
compiler.CompileLoadField(name, receiver, holder, field_index);
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
return code;
}
MaybeObject* StubCache::ComputeKeyedLoadConstant(String* name,
JSObject* receiver,
JSObject* holder,
Object* value) {
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Handle<Code> KeyedLoadStubCompiler::CompileLoadConstant(Handle<String> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Object> value) {
CALL_HEAP_FUNCTION(isolate(),
CompileLoadConstant(*name, *object, *holder, *value),
Code);
}
Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<Object> value) {
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Code::Flags flags =
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION);
Object* code = receiver->map()->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
HandleScope scope(isolate_);
KeyedLoadStubCompiler compiler(isolate_);
{ MaybeObject* maybe_code =
compiler.CompileLoadConstant(name, receiver, holder, value);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
PROFILE(isolate_,
CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
Object* result;
{ MaybeObject* maybe_result =
receiver->UpdateMapCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
}
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> code =
compiler.CompileLoadConstant(name, receiver, holder, value);
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
return code;
}
MaybeObject* StubCache::ComputeKeyedLoadInterceptor(String* name,
JSObject* receiver,
JSObject* holder) {
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Handle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor(
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<String> name) {
CALL_HEAP_FUNCTION(isolate(),
CompileLoadInterceptor(*object, *holder, *name),
Code);
}
Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSObject> holder) {
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Code::Flags flags =
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR);
Object* code = receiver->map()->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
HandleScope scope(isolate_);
KeyedLoadStubCompiler compiler(isolate_);
{ MaybeObject* maybe_code =
compiler.CompileLoadInterceptor(receiver, holder, name);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
PROFILE(isolate_,
CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
Object* result;
{ MaybeObject* maybe_result =
receiver->UpdateMapCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
}
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name);
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
return code;
}
MaybeObject* StubCache::ComputeKeyedLoadCallback(String* name,
JSObject* receiver,
JSObject* holder,
AccessorInfo* callback) {
ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP);
Handle<Code> KeyedLoadStubCompiler::CompileLoadCallback(
Handle<String> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<AccessorInfo> callback) {
CALL_HEAP_FUNCTION(isolate(),
CompileLoadCallback(*name, *object, *holder, *callback),
Code);
}
Handle<Code> StubCache::ComputeKeyedLoadCallback(
Handle<String> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<AccessorInfo> callback) {
ASSERT(IC::GetCodeCacheForObject(*receiver, *holder) == OWN_MAP);
Code::Flags flags =
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Object* code = receiver->map()->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
HandleScope scope(isolate_);
KeyedLoadStubCompiler compiler(isolate_);
{ MaybeObject* maybe_code =
compiler.CompileLoadCallback(name, receiver, holder, callback);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
PROFILE(isolate_,
CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
Object* result;
{ MaybeObject* maybe_result =
receiver->UpdateMapCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
}
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> code =
compiler.CompileLoadCallback(name, receiver, holder, callback);
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
return code;
}
Handle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength(
Handle<String> name) {
CALL_HEAP_FUNCTION(isolate(),
CompileLoadArrayLength(*name),
Code);
}
MaybeObject* StubCache::ComputeKeyedLoadArrayLength(String* name,
JSArray* receiver) {
Handle<Code> StubCache::ComputeKeyedLoadArrayLength(Handle<String> name,
Handle<JSArray> receiver) {
Code::Flags flags =
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
ASSERT(receiver->IsJSObject());
Object* code = receiver->map()->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
HandleScope scope(isolate_);
KeyedLoadStubCompiler compiler(isolate_);
{ MaybeObject* maybe_code = compiler.CompileLoadArrayLength(name);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
PROFILE(isolate_,
CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
Object* result;
{ MaybeObject* maybe_result =
receiver->UpdateMapCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
}
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> code = compiler.CompileLoadArrayLength(name);
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
return code;
}
MaybeObject* StubCache::ComputeKeyedLoadStringLength(String* name,
String* receiver) {
Handle<Code> KeyedLoadStubCompiler::CompileLoadStringLength(
Handle<String> name) {
CALL_HEAP_FUNCTION(isolate(),
CompileLoadStringLength(*name),
Code);
}
Handle<Code> StubCache::ComputeKeyedLoadStringLength(Handle<String> name,
Handle<String> receiver) {
Code::Flags flags =
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Map* map = receiver->map();
Object* code = map->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
HandleScope scope(isolate_);
KeyedLoadStubCompiler compiler(isolate_);
{ MaybeObject* maybe_code = compiler.CompileLoadStringLength(name);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
PROFILE(isolate_,
CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
Object* result;
{ MaybeObject* maybe_result = map->UpdateCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
}
Handle<Map> map(receiver->map());
Handle<Object> probe(map->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> code = compiler.CompileLoadStringLength(name);
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
Map::UpdateCodeCache(map, name, code);
return code;
}
MaybeObject* StubCache::ComputeKeyedLoadFunctionPrototype(
String* name,
JSFunction* receiver) {
Handle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype(
Handle<String> name) {
CALL_HEAP_FUNCTION(isolate(),
CompileLoadFunctionPrototype(*name),
Code);
}
Handle<Code> StubCache::ComputeKeyedLoadFunctionPrototype(
Handle<String> name,
Handle<JSFunction> receiver) {
Code::Flags flags =
Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS);
Object* code = receiver->map()->FindInCodeCache(name, flags);
if (code->IsUndefined()) {
HandleScope scope(isolate_);
KeyedLoadStubCompiler compiler(isolate_);
{ MaybeObject* maybe_code = compiler.CompileLoadFunctionPrototype(name);
if (!maybe_code->ToObject(&code)) return maybe_code;
}
PROFILE(isolate_,
CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, name, Code::cast(code)));
Object* result;
{ MaybeObject* maybe_result =
receiver->UpdateMapCodeCache(name, Code::cast(code));
if (!maybe_result->ToObject(&result)) return maybe_result;
}
}
Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags));
if (probe->IsCode()) return Handle<Code>::cast(probe);
KeyedLoadStubCompiler compiler(isolate_);
Handle<Code> code = compiler.CompileLoadFunctionPrototype(name);
PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name));
GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code));
JSObject::UpdateMapCodeCache(isolate_, receiver, name, code);
return code;
}

View File

@ -108,39 +108,33 @@ class StubCache {
// ---
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadField(String* name,
JSObject* receiver,
JSObject* holder,
int field_index);
Handle<Code> ComputeKeyedLoadField(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
int field_index);
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadCallback(
String* name,
JSObject* receiver,
JSObject* holder,
AccessorInfo* callback);
Handle<Code> ComputeKeyedLoadCallback(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<AccessorInfo> callback);
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadConstant(
String* name,
JSObject* receiver,
JSObject* holder,
Object* value);
Handle<Code> ComputeKeyedLoadConstant(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSObject> holder,
Handle<Object> value);
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadInterceptor(
String* name,
JSObject* receiver,
JSObject* holder);
Handle<Code> ComputeKeyedLoadInterceptor(Handle<String> name,
Handle<JSObject> receiver,
Handle<JSObject> holder);
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadArrayLength(
String* name,
JSArray* receiver);
Handle<Code> ComputeKeyedLoadArrayLength(Handle<String> name,
Handle<JSArray> receiver);
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadStringLength(
String* name,
String* receiver);
Handle<Code> ComputeKeyedLoadStringLength(Handle<String> name,
Handle<String> receiver);
MUST_USE_RESULT MaybeObject* ComputeKeyedLoadFunctionPrototype(
String* name,
JSFunction* receiver);
Handle<Code> ComputeKeyedLoadFunctionPrototype(Handle<String> name,
Handle<JSFunction> receiver);
// ---
@ -638,27 +632,55 @@ class LoadStubCompiler: public StubCompiler {
class KeyedLoadStubCompiler: public StubCompiler {
public:
explicit KeyedLoadStubCompiler(Isolate* isolate) : StubCompiler(isolate) { }
Handle<Code> CompileLoadField(Handle<String> name,
Handle<JSObject> object,
Handle<JSObject> holder,
int index);
MUST_USE_RESULT MaybeObject* CompileLoadField(String* name,
JSObject* object,
JSObject* holder,
int index);
Handle<Code> CompileLoadCallback(Handle<String> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<AccessorInfo> callback);
MUST_USE_RESULT MaybeObject* CompileLoadCallback(String* name,
JSObject* object,
JSObject* holder,
AccessorInfo* callback);
Handle<Code> CompileLoadConstant(Handle<String> name,
Handle<JSObject> object,
Handle<JSObject> holder,
Handle<Object> value);
MUST_USE_RESULT MaybeObject* CompileLoadConstant(String* name,
JSObject* object,
JSObject* holder,
Object* value);
Handle<Code> CompileLoadInterceptor(Handle<JSObject> object,
Handle<JSObject> holder,
Handle<String> name);
MUST_USE_RESULT MaybeObject* CompileLoadInterceptor(JSObject* object,
JSObject* holder,
String* name);
Handle<Code> CompileLoadArrayLength(Handle<String> name);
MUST_USE_RESULT MaybeObject* CompileLoadArrayLength(String* name);
Handle<Code> CompileLoadStringLength(Handle<String> name);
MUST_USE_RESULT MaybeObject* CompileLoadStringLength(String* name);
Handle<Code> CompileLoadFunctionPrototype(Handle<String> name);
MUST_USE_RESULT MaybeObject* CompileLoadFunctionPrototype(String* name);
MUST_USE_RESULT MaybeObject* CompileLoadElement(Map* receiver_map);