switch (target->kind()) {
case Code::LOAD_IC: return LoadIC::Clear(address, target);
- case Code::KEYED_LOAD_IC:
- return KeyedLoadIC::Clear(address, target);
+ case Code::KEYED_LOAD_IC: return KeyedLoadIC::Clear(address, target);
case Code::STORE_IC: return StoreIC::Clear(address, target);
- case Code::KEYED_STORE_IC:
- return KeyedStoreIC::Clear(address, target);
+ case Code::KEYED_STORE_IC: return KeyedStoreIC::Clear(address, target);
case Code::CALL_IC: return CallIC::Clear(address, target);
case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
case Code::COMPARE_IC: return CompareIC::Clear(address, target);
// Make sure to also clear the map used in inline fast cases. If we
// do not clear these maps, cached code can keep objects alive
// through the embedded maps.
- SetTargetAtAddress(address, initialize_stub());
+ SetTargetAtAddress(address, *initialize_stub());
}
void LoadIC::Clear(Address address, Code* target) {
if (target->ic_state() == UNINITIALIZED) return;
- SetTargetAtAddress(address, initialize_stub());
+ SetTargetAtAddress(address, *initialize_stub());
}
if (target->ic_state() == UNINITIALIZED) return;
SetTargetAtAddress(address,
(Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
- ? initialize_stub_strict()
- : initialize_stub());
+ ? *initialize_stub_strict()
+ : *initialize_stub());
}
if (target->ic_state() == UNINITIALIZED) return;
SetTargetAtAddress(address,
(Code::GetStrictMode(target->extra_ic_state()) == kStrictMode)
- ? initialize_stub_strict()
- : initialize_stub());
+ ? *initialize_stub_strict()
+ : *initialize_stub());
}
}
-MaybeObject* StoreIC::Store(State state,
- StrictModeFlag strict_mode,
- Handle<Object> object,
- Handle<String> name,
- Handle<Object> value) {
- if (!object->IsJSObject()) {
- // Handle proxies.
- if (object->IsJSProxy()) {
- return JSProxy::cast(*object)->
- SetProperty(*name, *value, NONE, strict_mode);
- }
+MaybeObject* IC::Store(State state,
+ StrictModeFlag strict_mode,
+ Handle<Object> object,
+ Handle<String> name,
+ Handle<Object> value,
+ JSReceiver::StoreFromKeyed store_mode) {
+ // Handle proxies.
+ if (object->IsJSProxy()) {
+ return JSProxy::cast(*object)->
+ SetProperty(*name, *value, NONE, strict_mode);
+ }
- // If the object is undefined or null it's illegal to try to set any
- // properties on it; throw a TypeError in that case.
- if (object->IsUndefined() || object->IsNull()) {
- return TypeError("non_object_property_store", object, name);
- }
+ // If the object is undefined or null it's illegal to try to set any
+ // properties on it; throw a TypeError in that case.
+ if (object->IsUndefined() || object->IsNull()) {
+ return TypeError("non_object_property_store", object, name);
+ }
- // The length property of string values is read-only. Throw in strict mode.
- if (strict_mode == kStrictMode && object->IsString() &&
- name->Equals(isolate()->heap()->length_symbol())) {
- return TypeError("strict_read_only_property", object, name);
- }
- // Ignore other stores where the receiver is not a JSObject.
- // TODO(1475): Must check prototype chains of object wrappers.
- return *value;
+ // The length property of string values is read-only. Throw in strict mode.
+ if (strict_mode == kStrictMode && object->IsString() &&
+ name->Equals(isolate()->heap()->length_symbol())) {
+ return TypeError("strict_read_only_property", object, name);
}
+ // Ignore other stores where the receiver is not a JSObject.
+ // TODO(1475): Must check prototype chains of object wrappers.
+ if (!object->IsJSObject()) return *value;
+
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
// Check if the given name is an array index.
// Observed objects are always modified through the runtime.
if (FLAG_harmony_observation && receiver->map()->is_observed()) {
- return receiver->SetProperty(*name, *value, NONE, strict_mode);
+ return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode);
}
// Use specialized code for setting the length of arrays with fast
- // properties. Slow properties might indicate redefinition of the
- // length property.
- if (receiver->IsJSArray() &&
+ // properties. Slow properties might indicate redefinition of the length
+ // property.
+ if (FLAG_use_ic &&
+ receiver->IsJSArray() &&
name->Equals(isolate()->heap()->length_symbol()) &&
Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
- receiver->HasFastProperties()) {
-#ifdef DEBUG
- if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n");
-#endif
+ receiver->HasFastProperties() &&
+ kind() != Code::KEYED_STORE_IC) {
Handle<Code> stub = (strict_mode == kStrictMode)
? isolate()->builtins()->StoreIC_ArrayLength_Strict()
: isolate()->builtins()->StoreIC_ArrayLength();
set_target(*stub);
- return receiver->SetProperty(*name, *value, NONE, strict_mode);
+ TRACE_IC("StoreIC", name, state, *stub);
+ return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode);
}
- // Lookup the property locally in the receiver.
- if (!receiver->IsJSGlobalProxy()) {
- LookupResult lookup(isolate());
-
- if (LookupForWrite(receiver, name, &lookup)) {
- if (FLAG_use_ic) { // Generate a stub for this store.
- UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
- }
- } else {
- // Strict mode doesn't allow setting non-existent global property
- // or an assignment to a read only property.
- if (strict_mode == kStrictMode) {
- if (lookup.IsProperty() && lookup.IsReadOnly()) {
- return TypeError("strict_read_only_property", object, name);
- } else if (IsContextual(object)) {
- return ReferenceError("not_defined", name);
- }
- }
+ if (receiver->IsJSGlobalProxy()) {
+ if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) {
+ // Generate a generic stub that goes to the runtime when we see a global
+ // proxy as receiver.
+ Handle<Code> stub = (strict_mode == kStrictMode)
+ ? global_proxy_stub_strict()
+ : global_proxy_stub();
+ set_target(*stub);
+ TRACE_IC("StoreIC", name, state, *stub);
}
+ return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode);
}
- if (receiver->IsJSGlobalProxy()) {
- // TODO(ulan): find out why we patch this site even with --no-use-ic
- // Generate a generic stub that goes to the runtime when we see a global
- // proxy as receiver.
- Handle<Code> stub = (strict_mode == kStrictMode)
- ? global_proxy_stub_strict()
- : global_proxy_stub();
- if (target() != *stub) {
- set_target(*stub);
- TRACE_IC("StoreIC", name, state, target());
+ LookupResult lookup(isolate());
+ if (LookupForWrite(receiver, name, &lookup)) {
+ if (FLAG_use_ic) {
+ UpdateStoreCaches(&lookup, state, strict_mode, receiver, name, value);
}
+ } else if (strict_mode == kStrictMode &&
+ !lookup.IsFound() &&
+ IsContextual(object)) {
+ // Strict mode doesn't allow setting non-existent global property
+ // or an assignment to a read only property.
+ return ReferenceError("not_defined", name);
}
// Set the property.
- return receiver->SetProperty(*name,
- *value,
- NONE,
- strict_mode,
- JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
+ return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode);
}
-void StoreIC::UpdateCaches(LookupResult* lookup,
- State state,
- StrictModeFlag strict_mode,
- Handle<JSObject> receiver,
- Handle<String> name,
- Handle<Object> value) {
+void StoreIC::UpdateStoreCaches(LookupResult* lookup,
+ State state,
+ StrictModeFlag strict_mode,
+ Handle<JSObject> receiver,
+ Handle<String> name,
+ Handle<Object> value) {
ASSERT(!receiver->IsJSGlobalProxy());
ASSERT(StoreICableLookup(lookup));
ASSERT(lookup->IsFound());
}
isolate()->stub_cache()->Set(*name, receiver->map(), *code);
set_target((strict_mode == kStrictMode)
- ? megamorphic_stub_strict()
+ ? *megamorphic_stub_strict()
: *megamorphic_stub());
}
break;
if (key->IsSymbol()) {
Handle<String> name = Handle<String>::cast(key);
-
- // Handle proxies.
- if (object->IsJSProxy()) {
- return JSProxy::cast(*object)->SetProperty(
- *name, *value, NONE, strict_mode);
- }
-
- // If the object is undefined or null it's illegal to try to set any
- // properties on it; throw a TypeError in that case.
- if (object->IsUndefined() || object->IsNull()) {
- return TypeError("non_object_property_store", object, name);
- }
-
- // Ignore stores where the receiver is not a JSObject.
- if (!object->IsJSObject()) return *value;
- Handle<JSObject> receiver = Handle<JSObject>::cast(object);
-
- // Check if the given name is an array index.
- uint32_t index;
- if (name->AsArrayIndex(&index)) {
- Handle<Object> result =
- JSObject::SetElement(receiver, index, value, NONE, strict_mode);
- RETURN_IF_EMPTY_HANDLE(isolate(), result);
- return *value;
- }
-
- // Update inline cache and stub cache.
- if (FLAG_use_ic && !receiver->IsJSGlobalProxy() &&
- !(FLAG_harmony_observation && receiver->map()->is_observed())) {
- LookupResult lookup(isolate());
- if (LookupForWrite(receiver, name, &lookup)) {
- UpdateCaches(&lookup, state, strict_mode, receiver, name, value);
- }
- }
-
- // Set the property.
- return receiver->SetProperty(*name, *value, NONE, strict_mode);
+ return IC::Store(state,
+ strict_mode,
+ object,
+ name,
+ value,
+ JSReceiver::MAY_BE_STORE_FROM_KEYED);
}
// Do not use ICs for objects that require access checks (including
}
-void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
- State state,
- StrictModeFlag strict_mode,
- Handle<JSObject> receiver,
- Handle<String> name,
- Handle<Object> value) {
+void KeyedStoreIC::UpdateStoreCaches(LookupResult* lookup,
+ State state,
+ StrictModeFlag strict_mode,
+ Handle<JSObject> receiver,
+ Handle<String> name,
+ Handle<Object> value) {
ASSERT(!receiver->IsJSGlobalProxy());
ASSERT(StoreICableLookup(lookup));
ASSERT(lookup->IsFound());
Handle<Object> object,
Handle<String> name);
+ MUST_USE_RESULT MaybeObject* Store(
+ State state,
+ StrictModeFlag strict_mode,
+ Handle<Object> object,
+ Handle<String> name,
+ Handle<Object> value,
+ JSReceiver::StoreFromKeyed store_mode =
+ JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED);
+
protected:
virtual Handle<Code> pre_monomorphic_stub() {
UNREACHABLE();
UNREACHABLE();
return Handle<Code>::null();
}
+ virtual Handle<Code> megamorphic_stub_strict() {
+ UNREACHABLE();
+ return Handle<Code>::null();
+ }
virtual Handle<Code> generic_stub() const {
UNREACHABLE();
return Handle<Code>::null();
UNREACHABLE();
return Code::STUB;
}
+ virtual Handle<Code> global_proxy_stub() {
+ UNREACHABLE();
+ return Handle<Code>::null();
+ }
+ virtual Handle<Code> global_proxy_stub_strict() {
+ UNREACHABLE();
+ return Handle<Code>::null();
+ }
+
virtual void UpdateLoadCaches(LookupResult* lookup,
State state,
Handle<Object> object,
Handle<String> name) {
UNREACHABLE();
}
+ virtual void UpdateStoreCaches(LookupResult* lookup,
+ State state,
+ StrictModeFlag strict_mode,
+ Handle<JSObject> receiver,
+ Handle<String> name,
+ Handle<Object> value) {
+ UNREACHABLE();
+ }
Address fp() const { return fp_; }
Address pc() const { return *pc_address_; }
Isolate* isolate() const { return isolate_; }
private:
// Stub accessors.
- static Code* initialize_stub() {
- return Isolate::Current()->builtins()->builtin(
- Builtins::kLoadIC_Initialize);
+ static Handle<Code> initialize_stub() {
+ return Isolate::Current()->builtins()->LoadIC_Initialize();
}
virtual Handle<Code> pre_monomorphic_stub() {
return isolate()->builtins()->LoadIC_PreMonomorphic();
private:
// Stub accessors.
- static Code* initialize_stub() {
- return Isolate::Current()->builtins()->builtin(
- Builtins::kKeyedLoadIC_Initialize);
+ static Handle<Code> initialize_stub() {
+ return Isolate::Current()->builtins()->KeyedLoadIC_Initialize();
}
virtual Handle<Code> pre_monomorphic_stub() {
return isolate()->builtins()->KeyedLoadIC_PreMonomorphic();
ASSERT(target()->is_store_stub());
}
- MUST_USE_RESULT MaybeObject* Store(State state,
- StrictModeFlag strict_mode,
- Handle<Object> object,
- Handle<String> name,
- Handle<Object> value);
-
// Code generators for stub routines. Only called once at startup.
static void GenerateInitialize(MacroAssembler* masm) { GenerateMiss(masm); }
static void GenerateMiss(MacroAssembler* masm);
virtual Handle<Code> megamorphic_stub() {
return isolate()->builtins()->StoreIC_Megamorphic();
}
+ // Stub accessors.
+ virtual Handle<Code> megamorphic_stub_strict() {
+ return isolate()->builtins()->StoreIC_Megamorphic_Strict();
+ }
+ virtual Handle<Code> global_proxy_stub() {
+ return isolate()->builtins()->StoreIC_GlobalProxy();
+ }
+ virtual Handle<Code> global_proxy_stub_strict() {
+ return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
+ }
+
- private:
// Update the inline cache and the global stub cache based on the
// lookup result.
- void UpdateCaches(LookupResult* lookup,
- State state,
- StrictModeFlag strict_mode,
- Handle<JSObject> receiver,
- Handle<String> name,
- Handle<Object> value);
+ virtual void UpdateStoreCaches(LookupResult* lookup,
+ State state,
+ StrictModeFlag strict_mode,
+ Handle<JSObject> receiver,
+ Handle<String> name,
+ Handle<Object> value);
+ private:
void set_target(Code* code) {
// Strict mode must be preserved across IC patching.
ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
IC::set_target(code);
}
- // Stub accessors.
- Code* megamorphic_stub_strict() {
- return isolate()->builtins()->builtin(
- Builtins::kStoreIC_Megamorphic_Strict);
- }
- static Code* initialize_stub() {
- return Isolate::Current()->builtins()->builtin(
- Builtins::kStoreIC_Initialize);
+ static Handle<Code> initialize_stub() {
+ return Isolate::Current()->builtins()->StoreIC_Initialize();
}
- static Code* initialize_stub_strict() {
- return Isolate::Current()->builtins()->builtin(
- Builtins::kStoreIC_Initialize_Strict);
+ static Handle<Code> initialize_stub_strict() {
+ return Isolate::Current()->builtins()->StoreIC_Initialize_Strict();
}
- Handle<Code> global_proxy_stub() {
- return isolate()->builtins()->StoreIC_GlobalProxy();
- }
- Handle<Code> global_proxy_stub_strict() {
- return isolate()->builtins()->StoreIC_GlobalProxy_Strict();
- }
-
static void Clear(Address address, Code* target);
friend class IC;
StrictModeFlag strict_mode,
KeyedAccessGrowMode grow_mode);
- private:
// Update the inline cache.
- void UpdateCaches(LookupResult* lookup,
- State state,
- StrictModeFlag strict_mode,
- Handle<JSObject> receiver,
- Handle<String> name,
- Handle<Object> value);
+ virtual void UpdateStoreCaches(LookupResult* lookup,
+ State state,
+ StrictModeFlag strict_mode,
+ Handle<JSObject> receiver,
+ Handle<String> name,
+ Handle<Object> value);
+
+ virtual Handle<Code> megamorphic_stub() {
+ return isolate()->builtins()->KeyedStoreIC_Generic();
+ }
+ virtual Handle<Code> megamorphic_stub_strict() {
+ return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
+ }
+ private:
void set_target(Code* code) {
// Strict mode must be preserved across IC patching.
ASSERT(Code::GetStrictMode(code->extra_ic_state()) ==
}
// Stub accessors.
- static Code* initialize_stub() {
- return Isolate::Current()->builtins()->builtin(
- Builtins::kKeyedStoreIC_Initialize);
- }
- static Code* initialize_stub_strict() {
- return Isolate::Current()->builtins()->builtin(
- Builtins::kKeyedStoreIC_Initialize_Strict);
+ static Handle<Code> initialize_stub() {
+ return Isolate::Current()->builtins()->KeyedStoreIC_Initialize();
}
- Handle<Code> megamorphic_stub() {
- return isolate()->builtins()->KeyedStoreIC_Generic();
- }
- Handle<Code> megamorphic_stub_strict() {
- return isolate()->builtins()->KeyedStoreIC_Generic_Strict();
+ static Handle<Code> initialize_stub_strict() {
+ return Isolate::Current()->builtins()->KeyedStoreIC_Initialize_Strict();
}
Handle<Code> generic_stub() const {
return isolate()->builtins()->KeyedStoreIC_Generic();