}
-bool IC::HandleLoad(State state,
- Handle<Object> object,
- Handle<String> name,
- MaybeObject** result) {
+MaybeObject* IC::Load(State state,
+ Handle<Object> object,
+ Handle<String> name) {
+ // If the object is undefined or null it's illegal to try to get any
+ // of its properties; throw a TypeError in that case.
+ if (object->IsUndefined() || object->IsNull()) {
+ return TypeError("non_object_property_load", object, name);
+ }
+
if (FLAG_use_ic) {
// Use specialized code for getting the length of strings and
// string wrapper objects. The length property of string wrapper
Handle<Object> string = object->IsJSValue()
? Handle<Object>(Handle<JSValue>::cast(object)->value())
: object;
- *result = Smi::FromInt(String::cast(*string)->length());
- return true;
+ return Smi::FromInt(String::cast(*string)->length());
}
// Use specialized code for getting the length of arrays.
if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
#endif
}
- *result = JSArray::cast(*object)->length();
- return true;
+ return JSArray::cast(*object)->length();
}
// Use specialized code for getting prototype of functions.
if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
#endif
}
- *result = Accessors::FunctionGetPrototype(*object, 0);
- return true;
+ return Accessors::FunctionGetPrototype(*object, 0);
}
}
- return false;
-}
-
-
-MaybeObject* LoadIC::Load(State state,
- Handle<Object> object,
- Handle<String> name) {
- // If the object is undefined or null it's illegal to try to get any
- // of its properties; throw a TypeError in that case.
- if (object->IsUndefined() || object->IsNull()) {
- return TypeError("non_object_property_load", object, name);
- }
-
- MaybeObject* result;
- if (HandleLoad(state, object, name, &result)) {
- return result;
- }
-
// Check if the name is trivially convertible to an index and get
- // the element if so.
+ // the element or char if so.
uint32_t index;
- if (name->AsArrayIndex(&index)) return object->GetElement(index);
+ if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) {
+ // Rewrite to the generic keyed load stub.
+ if (FLAG_use_ic) set_target(*generic_stub());
+ return Runtime::GetElementOrCharAt(isolate(), object, index);
+ }
// Named lookup in the object.
LookupResult lookup(isolate());
// Update inline cache and stub cache.
if (FLAG_use_ic) {
- UpdateCaches(&lookup, state, object, name);
+ UpdateLoadCaches(&lookup, state, object, name);
}
PropertyAttributes attr;
}
-void LoadIC::UpdateCaches(LookupResult* lookup,
- State state,
- Handle<Object> object,
- Handle<String> name) {
+void LoadIC::UpdateLoadCaches(LookupResult* lookup,
+ State state,
+ Handle<Object> object,
+ Handle<String> name) {
// Bail out if the result is not cacheable.
if (!lookup->IsCacheable()) return;
key = TryConvertKey(key, isolate());
if (key->IsSymbol()) {
- Handle<String> name = Handle<String>::cast(key);
-
- // If the object is undefined or null it's illegal to try to get any
- // of its properties; throw a TypeError in that case.
- if (object->IsUndefined() || object->IsNull()) {
- return TypeError("non_object_property_load", object, name);
- }
-
- MaybeObject* result;
- if (HandleLoad(state, object, name, &result)) {
- return result;
- }
-
- // Check if the name is trivially convertible to an index and get
- // the element or char if so.
- uint32_t index = 0;
- if (name->AsArrayIndex(&index)) {
- // Rewrite to the generic keyed load stub.
- if (FLAG_use_ic) set_target(*generic_stub());
- return Runtime::GetElementOrCharAt(isolate(), object, index);
- }
-
- // Named lookup.
- LookupResult lookup(isolate());
- LookupForRead(object, name, &lookup);
-
- // If we did not find a property, check if we need to throw an exception.
- if (!lookup.IsFound() && IsContextual(object)) {
- return ReferenceError("not_defined", name);
- }
-
- if (FLAG_use_ic) {
- UpdateCaches(&lookup, state, object, name);
- }
-
- PropertyAttributes attr;
- if (lookup.IsInterceptor()) {
- // Get the property.
- 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 object->GetProperty(*object, &lookup, *name, &attr);
+ return IC::Load(state, object, Handle<String>::cast(key));
}
// Do not use ICs for objects that require access checks (including
} else if (receiver->HasIndexedInterceptor()) {
stub = indexed_interceptor_stub();
} else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
- stub = ComputeStub(receiver, LOAD, kNonStrictMode, stub);
+ stub = ComputeStub(receiver, KeyedIC::LOAD, kNonStrictMode, stub);
}
}
} else {
}
-void KeyedLoadIC::UpdateCaches(LookupResult* lookup,
- State state,
- Handle<Object> object,
- Handle<String> name) {
+void KeyedLoadIC::UpdateLoadCaches(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;
static inline JSObject* GetCodeCacheHolder(Object* object,
InlineCacheHolderFlag holder);
+ MUST_USE_RESULT MaybeObject* Load(State state,
+ Handle<Object> object,
+ Handle<String> name);
+
protected:
virtual Handle<Code> pre_monomorphic_stub() {
UNREACHABLE();
UNREACHABLE();
return Handle<Code>::null();
}
+ virtual Handle<Code> generic_stub() const {
+ UNREACHABLE();
+ return Handle<Code>::null();
+ }
virtual Code::Kind kind() const {
UNREACHABLE();
return Code::STUB;
}
+ virtual void UpdateLoadCaches(LookupResult* lookup,
+ State state,
+ Handle<Object> object,
+ Handle<String> name) {
+ UNREACHABLE();
+ }
Address fp() const { return fp_; }
Address pc() const { return *pc_address_; }
Isolate* isolate() const { return isolate_; }
static inline void SetTargetAtAddress(Address address, Code* target);
static void PostPatching(Address address, Code* target, Code* old_target);
- bool HandleLoad(State state,
- Handle<Object> object,
- Handle<String> name,
- MaybeObject** result);
-
private:
// Frame pointer for the frame that uses (calls) the IC.
Address fp_;
ASSERT(target()->is_load_stub());
}
- MUST_USE_RESULT MaybeObject* Load(State state,
- Handle<Object> object,
- Handle<String> name);
-
// Code generator routines.
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
static void GeneratePreMonomorphic(MacroAssembler* masm) {
return isolate()->builtins()->LoadIC_Megamorphic();
}
- private:
// Update the inline cache and the global stub cache based on the
// lookup result.
- void UpdateCaches(LookupResult* lookup,
- State state,
- Handle<Object> object,
- Handle<String> name);
+ virtual void UpdateLoadCaches(LookupResult* lookup,
+ State state,
+ Handle<Object> object,
+ Handle<String> name);
+ private:
// Stub accessors.
static Code* initialize_stub() {
return Isolate::Current()->builtins()->builtin(
virtual Handle<Code> megamorphic_stub() {
return isolate()->builtins()->KeyedLoadIC_Generic();
}
+ virtual Handle<Code> generic_stub() const {
+ return isolate()->builtins()->KeyedLoadIC_Generic();
+ }
virtual Handle<Code> ComputePolymorphicStub(MapHandleList* receiver_maps,
StrictModeFlag strict_mode,
return isolate()->builtins()->KeyedLoadIC_String();
}
- private:
// Update the inline cache.
- void UpdateCaches(LookupResult* lookup,
- State state,
- Handle<Object> object,
- Handle<String> name);
+ virtual void UpdateLoadCaches(LookupResult* lookup,
+ State state,
+ Handle<Object> object,
+ Handle<String> name);
+ private:
// Stub accessors.
static Code* initialize_stub() {
return Isolate::Current()->builtins()->builtin(
Builtins::kKeyedLoadIC_Initialize);
}
- Handle<Code> generic_stub() const {
- return isolate()->builtins()->KeyedLoadIC_Generic();
- }
virtual Handle<Code> pre_monomorphic_stub() {
return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
}