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:
parent
655b2332d7
commit
f985b15aae
196
src/ic.cc
196
src/ic.cc
@ -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]);
|
||||
|
39
src/ic.h
39
src/ic.h
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user