Commit 3384a793 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ic] Introduce proper slow stub for StoreGlobalIC.

Bug: chromium:768875
Change-Id: Ib5b324e90bea846e6cca419f81bf46bd293e83b4
Reviewed-on: https://chromium-review.googlesource.com/715802Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48503}
parent efd7c594
......@@ -213,6 +213,7 @@ namespace internal {
TFH(LoadIC_Slow, LoadWithVector) \
TFH(LoadIC_StringLength, LoadWithVector) \
TFH(LoadIC_Uninitialized, LoadWithVector) \
TFH(StoreGlobalIC_Slow, StoreWithVector) \
TFH(StoreIC_Miss, StoreWithVector) \
ASM(StoreIC_Setter_ForDeopt) \
TFH(StoreIC_Uninitialized, StoreWithVector) \
......
......@@ -167,5 +167,19 @@ void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
}
TF_BUILTIN(StoreGlobalIC_Slow, CodeStubAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver);
Node* name = Parameter(Descriptor::kName);
Node* value = Parameter(Descriptor::kValue);
Node* slot = Parameter(Descriptor::kSlot);
Node* vector = Parameter(Descriptor::kVector);
Node* context = Parameter(Descriptor::kContext);
// The slow case calls into the runtime to complete the store without causing
// an IC miss that would otherwise cause a transition to the generic stub.
TailCallRuntime(Runtime::kStoreGlobalIC_Slow, context, value, slot, vector,
receiver, name);
}
} // namespace internal
} // namespace v8
......@@ -2139,6 +2139,48 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) {
}
}
RUNTIME_FUNCTION(Runtime_StoreGlobalIC_Slow) {
HandleScope scope(isolate);
DCHECK_EQ(5, args.length());
// Runtime functions don't follow the IC's calling convention.
Handle<Object> value = args.at(0);
Handle<Smi> slot = args.at<Smi>(1);
Handle<FeedbackVector> vector = args.at<FeedbackVector>(2);
Handle<Object> object = args.at(3);
CONVERT_ARG_HANDLE_CHECKED(String, name, 4);
Handle<Context> native_context = isolate->native_context();
Handle<ScriptContextTable> script_contexts(
native_context->script_context_table());
ScriptContextTable::LookupResult lookup_result;
if (ScriptContextTable::Lookup(script_contexts, name, &lookup_result)) {
Handle<Context> script_context = ScriptContextTable::GetContext(
script_contexts, lookup_result.context_index);
if (lookup_result.mode == CONST) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewTypeError(MessageTemplate::kConstAssign, object, name));
}
Handle<Object> previous_value =
FixedArray::get(*script_context, lookup_result.slot_index, isolate);
if (previous_value->IsTheHole(isolate)) {
THROW_NEW_ERROR_RETURN_FAILURE(
isolate, NewReferenceError(MessageTemplate::kNotDefined, name));
}
script_context->set(lookup_result.slot_index, *value);
return *value;
}
FeedbackSlot vector_slot = vector->ToSlot(slot->value());
LanguageMode language_mode = vector->GetLanguageMode(vector_slot);
RETURN_RESULT_OR_FAILURE(
isolate,
Runtime::SetObjectProperty(isolate, object, name, value, language_mode));
}
// Used from ic-<arch>.cc.
RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) {
HandleScope scope(isolate);
......
......@@ -321,7 +321,7 @@ class StoreIC : public IC {
protected:
// Stub accessors.
Handle<Code> slow_stub() const {
virtual Handle<Code> slow_stub() const {
// All StoreICs share the same slow stub.
return BUILTIN_CODE(isolate(), KeyedStoreIC_Slow);
}
......@@ -348,6 +348,11 @@ class StoreGlobalIC : public StoreIC {
MUST_USE_RESULT MaybeHandle<Object> Store(Handle<Object> object,
Handle<Name> name,
Handle<Object> value);
protected:
Handle<Code> slow_stub() const override {
return BUILTIN_CODE(isolate(), StoreGlobalIC_Slow);
}
};
enum KeyedStoreCheckMap { kDontCheckMap, kCheckMap };
......
......@@ -671,6 +671,7 @@ namespace internal {
F(LoadIC_Miss, 4, 1) \
F(LoadPropertyWithInterceptor, 5, 1) \
F(StoreCallbackProperty, 6, 1) \
F(StoreGlobalIC_Slow, 5, 1) \
F(StoreIC_Miss, 5, 1) \
F(StorePropertyWithInterceptor, 5, 1) \
F(Unreachable, 0, 1)
......
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
this.__defineGetter__('x', function() { return 0; });
function store_x() {
x = 23;
}
store_x();
store_x();
assertEquals(0, x);
Realm.eval(Realm.current(), "let x = 42");
assertEquals(42, x);
store_x();
assertEquals(23, x);
this.__defineGetter__('y', function() { return 0; });
function store_y() {
y = 23;
}
store_y();
store_y();
assertEquals(0, y);
Realm.eval(Realm.current(), "const y = 42");
assertEquals(42, y);
assertThrows(store_y, TypeError);
assertEquals(42, y);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment