Commit 6767c3de authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[ic] Encode lexical variable access as a smi in Load/StoreGlobalIC.

This CL removes LoadScriptContextFieldStub and StoreScriptContextFieldStub.

Bug: v8:7206, chromium:576312
Change-Id: I217eeb726ca7d1ec85a67331da4941b9ac2a4b7a
Reviewed-on: https://chromium-review.googlesource.com/831867Reviewed-by: 's avatarRoss McIlroy <rmcilroy@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50177}
parent 3928133c
...@@ -5208,7 +5208,8 @@ TNode<Number> CodeStubAssembler::StringToNumber(SloppyTNode<Context> context, ...@@ -5208,7 +5208,8 @@ TNode<Number> CodeStubAssembler::StringToNumber(SloppyTNode<Context> context,
GotoIf(IsSetWord32(hash, Name::kDoesNotContainCachedArrayIndexMask), GotoIf(IsSetWord32(hash, Name::kDoesNotContainCachedArrayIndexMask),
&runtime); &runtime);
var_result = SmiTag(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash)); var_result =
SmiTag(Signed(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash)));
Goto(&end); Goto(&end);
BIND(&runtime); BIND(&runtime);
...@@ -5866,8 +5867,10 @@ TNode<Uint32T> CodeStubAssembler::DecodeWord32(SloppyTNode<Word32T> word32, ...@@ -5866,8 +5867,10 @@ TNode<Uint32T> CodeStubAssembler::DecodeWord32(SloppyTNode<Word32T> word32,
Word32And(word32, Int32Constant(mask)), static_cast<int>(shift))); Word32And(word32, Int32Constant(mask)), static_cast<int>(shift)));
} }
Node* CodeStubAssembler::DecodeWord(Node* word, uint32_t shift, uint32_t mask) { TNode<UintPtrT> CodeStubAssembler::DecodeWord(SloppyTNode<WordT> word,
return WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift)); uint32_t shift, uint32_t mask) {
return Unsigned(
WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift)));
} }
Node* CodeStubAssembler::UpdateWord(Node* word, Node* value, uint32_t shift, Node* CodeStubAssembler::UpdateWord(Node* word, Node* value, uint32_t shift,
...@@ -7509,15 +7512,16 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, ...@@ -7509,15 +7512,16 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key,
return var_result.value(); return var_result.value();
} }
Node* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) { TNode<Context> CodeStubAssembler::LoadScriptContext(
Node* native_context = LoadNativeContext(context); TNode<Context> context, TNode<IntPtrT> context_index) {
Node* script_context_table = TNode<Context> native_context = LoadNativeContext(context);
LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX); TNode<ScriptContextTable> script_context_table = CAST(
LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX));
int offset = Node* script_context = LoadFixedArrayElement(
ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag; script_context_table, context_index,
return Load(MachineType::AnyTagged(), script_context_table, ScriptContextTable::kFirstContextSlotIndex * kPointerSize);
IntPtrConstant(offset)); return CAST(script_context);
} }
namespace { namespace {
......
...@@ -1248,22 +1248,23 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1248,22 +1248,23 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Returns a node that contains a decoded (unsigned!) value of a bit // Returns a node that contains a decoded (unsigned!) value of a bit
// field |BitField| in |word|. Returns result as a word-size node. // field |BitField| in |word|. Returns result as a word-size node.
template <typename BitField> template <typename BitField>
Node* DecodeWord(Node* word) { TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word) {
return DecodeWord(word, BitField::kShift, BitField::kMask); return DecodeWord(word, BitField::kShift, BitField::kMask);
} }
// Returns a node that contains a decoded (unsigned!) value of a bit // Returns a node that contains a decoded (unsigned!) value of a bit
// field |BitField| in |word32|. Returns result as a word-size node. // field |BitField| in |word32|. Returns result as a word-size node.
template <typename BitField> template <typename BitField>
Node* DecodeWordFromWord32(Node* word32) { TNode<UintPtrT> DecodeWordFromWord32(SloppyTNode<Word32T> word32) {
return DecodeWord<BitField>(ChangeUint32ToWord(word32)); return DecodeWord<BitField>(ChangeUint32ToWord(word32));
} }
// Returns a node that contains a decoded (unsigned!) value of a bit // Returns a node that contains a decoded (unsigned!) value of a bit
// field |BitField| in |word|. Returns result as an uint32 node. // field |BitField| in |word|. Returns result as an uint32 node.
template <typename BitField> template <typename BitField>
Node* DecodeWord32FromWord(Node* word) { TNode<Uint32T> DecodeWord32FromWord(SloppyTNode<WordT> word) {
return TruncateWordToWord32(DecodeWord<BitField>(word)); return UncheckedCast<Uint32T>(
TruncateWordToWord32(Signed(DecodeWord<BitField>(word))));
} }
// Decodes an unsigned (!) value from |word32| to an uint32 node. // Decodes an unsigned (!) value from |word32| to an uint32 node.
...@@ -1271,7 +1272,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1271,7 +1272,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
uint32_t mask); uint32_t mask);
// Decodes an unsigned (!) value from |word| to a word-size node. // Decodes an unsigned (!) value from |word| to a word-size node.
Node* DecodeWord(Node* word, uint32_t shift, uint32_t mask); TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word, uint32_t shift,
uint32_t mask);
// Returns a node that contains the updated values of a |BitField|. // Returns a node that contains the updated values of a |BitField|.
template <typename BitField> template <typename BitField>
...@@ -1663,7 +1665,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1663,7 +1665,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
} }
// Loads script context from the script context table. // Loads script context from the script context table.
Node* LoadScriptContext(Node* context, int context_index); TNode<Context> LoadScriptContext(TNode<Context> context,
TNode<IntPtrT> context_index);
Node* Int32ToUint8Clamped(Node* int32_value); Node* Int32ToUint8Clamped(Node* int32_value);
Node* Float64ToUint8Clamped(Node* float64_value); Node* Float64ToUint8Clamped(Node* float64_value);
......
...@@ -404,30 +404,6 @@ TF_STUB(KeyedStoreSloppyArgumentsStub, CodeStubAssembler) { ...@@ -404,30 +404,6 @@ TF_STUB(KeyedStoreSloppyArgumentsStub, CodeStubAssembler) {
} }
} }
TF_STUB(LoadScriptContextFieldStub, CodeStubAssembler) {
Comment("LoadScriptContextFieldStub: context_index=%d, slot=%d",
stub->context_index(), stub->slot_index());
Node* context = Parameter(Descriptor::kContext);
Node* script_context = LoadScriptContext(context, stub->context_index());
Node* result = LoadFixedArrayElement(script_context, stub->slot_index());
Return(result);
}
TF_STUB(StoreScriptContextFieldStub, CodeStubAssembler) {
Comment("StoreScriptContextFieldStub: context_index=%d, slot=%d",
stub->context_index(), stub->slot_index());
Node* value = Parameter(Descriptor::kValue);
Node* context = Parameter(Descriptor::kContext);
Node* script_context = LoadScriptContext(context, stub->context_index());
StoreFixedArrayElement(script_context, IntPtrConstant(stub->slot_index()),
value);
Return(value);
}
// TODO(ishell): move to builtins-handler-gen. // TODO(ishell): move to builtins-handler-gen.
TF_STUB(StoreInterceptorStub, CodeStubAssembler) { TF_STUB(StoreInterceptorStub, CodeStubAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver); Node* receiver = Parameter(Descriptor::kReceiver);
......
...@@ -47,8 +47,6 @@ class Node; ...@@ -47,8 +47,6 @@ class Node;
V(ElementsTransitionAndStore) \ V(ElementsTransitionAndStore) \
V(KeyedLoadSloppyArguments) \ V(KeyedLoadSloppyArguments) \
V(KeyedStoreSloppyArguments) \ V(KeyedStoreSloppyArguments) \
V(LoadScriptContextField) \
V(StoreScriptContextField) \
V(StringAdd) \ V(StringAdd) \
V(GetProperty) \ V(GetProperty) \
V(StoreFastElement) \ V(StoreFastElement) \
...@@ -793,59 +791,6 @@ class DoubleToIStub : public PlatformCodeStub { ...@@ -793,59 +791,6 @@ class DoubleToIStub : public PlatformCodeStub {
DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub); DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
}; };
class ScriptContextFieldStub : public TurboFanCodeStub {
public:
ScriptContextFieldStub(Isolate* isolate,
const ScriptContextTable::LookupResult* lookup_result)
: TurboFanCodeStub(isolate) {
DCHECK(Accepted(lookup_result));
minor_key_ = ContextIndexBits::encode(lookup_result->context_index) |
SlotIndexBits::encode(lookup_result->slot_index);
}
int context_index() const { return ContextIndexBits::decode(minor_key_); }
int slot_index() const { return SlotIndexBits::decode(minor_key_); }
static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
return ContextIndexBits::is_valid(lookup_result->context_index) &&
SlotIndexBits::is_valid(lookup_result->slot_index);
}
private:
static const int kContextIndexBits = 9;
static const int kSlotIndexBits = 12;
class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
class SlotIndexBits
: public BitField<int, kContextIndexBits, kSlotIndexBits> {};
DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, TurboFanCodeStub);
};
class LoadScriptContextFieldStub : public ScriptContextFieldStub {
public:
LoadScriptContextFieldStub(
Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
: ScriptContextFieldStub(isolate, lookup_result) {}
private:
DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
DEFINE_TURBOFAN_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
};
class StoreScriptContextFieldStub : public ScriptContextFieldStub {
public:
StoreScriptContextFieldStub(
Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
: ScriptContextFieldStub(isolate, lookup_result) {}
private:
DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
DEFINE_TURBOFAN_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
};
class StoreFastElementStub : public TurboFanCodeStub { class StoreFastElementStub : public TurboFanCodeStub {
public: public:
StoreFastElementStub(Isolate* isolate, bool is_js_array, StoreFastElementStub(Isolate* isolate, bool is_js_array,
......
...@@ -1067,6 +1067,11 @@ class V8_EXPORT_PRIVATE CodeAssembler { ...@@ -1067,6 +1067,11 @@ class V8_EXPORT_PRIVATE CodeAssembler {
bool Word32ShiftIsSafe() const; bool Word32ShiftIsSafe() const;
private: private:
// These two don't have definitions and are here only for catching use cases
// where the cast is not necessary.
TNode<Int32T> Signed(TNode<Int32T> x);
TNode<Uint32T> Unsigned(TNode<Uint32T> x);
RawMachineAssembler* raw_assembler() const; RawMachineAssembler* raw_assembler() const;
// Calls respective callback registered in the state. // Calls respective callback registered in the state.
......
...@@ -24,10 +24,10 @@ ScriptContextTable* ScriptContextTable::cast(Object* context) { ...@@ -24,10 +24,10 @@ ScriptContextTable* ScriptContextTable::cast(Object* context) {
return reinterpret_cast<ScriptContextTable*>(context); return reinterpret_cast<ScriptContextTable*>(context);
} }
int ScriptContextTable::used() const { return Smi::ToInt(get(kUsedSlot)); } int ScriptContextTable::used() const { return Smi::ToInt(get(kUsedSlotIndex)); }
void ScriptContextTable::set_used(int used) { void ScriptContextTable::set_used(int used) {
set(kUsedSlot, Smi::FromInt(used)); set(kUsedSlotIndex, Smi::FromInt(used));
} }
...@@ -36,7 +36,7 @@ Handle<Context> ScriptContextTable::GetContext(Handle<ScriptContextTable> table, ...@@ -36,7 +36,7 @@ Handle<Context> ScriptContextTable::GetContext(Handle<ScriptContextTable> table,
int i) { int i) {
DCHECK(i < table->used()); DCHECK(i < table->used());
return Handle<Context>::cast( return Handle<Context>::cast(
FixedArray::get(*table, i + kFirstContextSlot, table->GetIsolate())); FixedArray::get(*table, i + kFirstContextSlotIndex, table->GetIsolate()));
} }
......
...@@ -19,7 +19,7 @@ Handle<ScriptContextTable> ScriptContextTable::Extend( ...@@ -19,7 +19,7 @@ Handle<ScriptContextTable> ScriptContextTable::Extend(
int used = table->used(); int used = table->used();
int length = table->length(); int length = table->length();
CHECK(used >= 0 && length > 0 && used < length); CHECK(used >= 0 && length > 0 && used < length);
if (used + kFirstContextSlot == length) { if (used + kFirstContextSlotIndex == length) {
CHECK(length < Smi::kMaxValue / 2); CHECK(length < Smi::kMaxValue / 2);
Isolate* isolate = table->GetIsolate(); Isolate* isolate = table->GetIsolate();
Handle<FixedArray> copy = Handle<FixedArray> copy =
...@@ -32,7 +32,7 @@ Handle<ScriptContextTable> ScriptContextTable::Extend( ...@@ -32,7 +32,7 @@ Handle<ScriptContextTable> ScriptContextTable::Extend(
result->set_used(used + 1); result->set_used(used + 1);
DCHECK(script_context->IsScriptContext()); DCHECK(script_context->IsScriptContext());
result->set(used + kFirstContextSlot, *script_context); result->set(used + kFirstContextSlotIndex, *script_context);
return result; return result;
} }
......
...@@ -450,15 +450,8 @@ class ScriptContextTable : public FixedArray { ...@@ -450,15 +450,8 @@ class ScriptContextTable : public FixedArray {
static Handle<ScriptContextTable> Extend(Handle<ScriptContextTable> table, static Handle<ScriptContextTable> Extend(Handle<ScriptContextTable> table,
Handle<Context> script_context); Handle<Context> script_context);
static int GetContextOffset(int context_index) { static const int kUsedSlotIndex = 0;
return kFirstContextOffset + context_index * kPointerSize; static const int kFirstContextSlotIndex = 1;
}
private:
static const int kUsedSlot = 0;
static const int kFirstContextSlot = kUsedSlot + 1;
static const int kFirstContextOffset =
FixedArray::kHeaderSize + kFirstContextSlot * kPointerSize;
DISALLOW_IMPLICIT_CONSTRUCTORS(ScriptContextTable); DISALLOW_IMPLICIT_CONSTRUCTORS(ScriptContextTable);
}; };
......
...@@ -881,6 +881,8 @@ class RuntimeCallTimer final { ...@@ -881,6 +881,8 @@ class RuntimeCallTimer final {
V(KeyedStoreIC_SlowStub) \ V(KeyedStoreIC_SlowStub) \
V(KeyedStoreIC_StoreFastElementStub) \ V(KeyedStoreIC_StoreFastElementStub) \
V(KeyedStoreIC_StoreElementStub) \ V(KeyedStoreIC_StoreElementStub) \
V(LoadGlobalIC_LoadScriptContextField) \
V(LoadGlobalIC_SlowStub) \
V(LoadIC_FunctionPrototypeStub) \ V(LoadIC_FunctionPrototypeStub) \
V(LoadIC_HandlerCacheHit_Accessor) \ V(LoadIC_HandlerCacheHit_Accessor) \
V(LoadIC_LoadAccessorDH) \ V(LoadIC_LoadAccessorDH) \
...@@ -902,12 +904,13 @@ class RuntimeCallTimer final { ...@@ -902,12 +904,13 @@ class RuntimeCallTimer final {
V(LoadIC_LoadNonexistentDH) \ V(LoadIC_LoadNonexistentDH) \
V(LoadIC_LoadNormalDH) \ V(LoadIC_LoadNormalDH) \
V(LoadIC_LoadNormalFromPrototypeDH) \ V(LoadIC_LoadNormalFromPrototypeDH) \
V(LoadIC_LoadScriptContextFieldStub) \
V(LoadIC_NonReceiver) \ V(LoadIC_NonReceiver) \
V(LoadIC_Premonomorphic) \ V(LoadIC_Premonomorphic) \
V(LoadIC_SlowStub) \ V(LoadIC_SlowStub) \
V(LoadIC_StringLength) \ V(LoadIC_StringLength) \
V(LoadIC_StringWrapperLength) \ V(LoadIC_StringWrapperLength) \
V(StoreGlobalIC_StoreScriptContextField) \
V(StoreGlobalIC_SlowStub) \
V(StoreIC_HandlerCacheHit_Accessor) \ V(StoreIC_HandlerCacheHit_Accessor) \
V(StoreIC_NonReceiver) \ V(StoreIC_NonReceiver) \
V(StoreIC_Premonomorphic) \ V(StoreIC_Premonomorphic) \
...@@ -922,7 +925,6 @@ class RuntimeCallTimer final { ...@@ -922,7 +925,6 @@ class RuntimeCallTimer final {
V(StoreIC_StoreNativeDataPropertyDH) \ V(StoreIC_StoreNativeDataPropertyDH) \
V(StoreIC_StoreNativeDataPropertyOnPrototypeDH) \ V(StoreIC_StoreNativeDataPropertyOnPrototypeDH) \
V(StoreIC_StoreNormalDH) \ V(StoreIC_StoreNormalDH) \
V(StoreIC_StoreScriptContextFieldStub) \
V(StoreIC_StoreTransitionDH) V(StoreIC_StoreTransitionDH)
enum RuntimeCallCounterId { enum RuntimeCallCounterId {
......
...@@ -579,18 +579,6 @@ InlineCacheState LoadICNexus::StateFromFeedback() const { ...@@ -579,18 +579,6 @@ InlineCacheState LoadICNexus::StateFromFeedback() const {
return UNINITIALIZED; return UNINITIALIZED;
} }
InlineCacheState LoadGlobalICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
Object* extra = GetFeedbackExtra();
if (!WeakCell::cast(feedback)->cleared() ||
extra != *FeedbackVector::UninitializedSentinel(isolate)) {
return MONOMORPHIC;
}
return UNINITIALIZED;
}
InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate(); Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback(); Object* feedback = GetFeedback();
...@@ -617,28 +605,47 @@ InlineCacheState KeyedLoadICNexus::StateFromFeedback() const { ...@@ -617,28 +605,47 @@ InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
return UNINITIALIZED; return UNINITIALIZED;
} }
void StoreGlobalICNexus::ConfigureUninitialized() { void GlobalICNexus::ConfigureUninitialized() {
Isolate* isolate = GetIsolate(); Isolate* isolate = GetIsolate();
SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER); SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate), SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
} }
void StoreGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) { void GlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
Isolate* isolate = GetIsolate(); Isolate* isolate = GetIsolate();
SetFeedback(*isolate->factory()->NewWeakCell(cell)); SetFeedback(*isolate->factory()->NewWeakCell(cell));
SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate), SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
} }
void StoreGlobalICNexus::ConfigureHandlerMode(Handle<Object> handler) { bool GlobalICNexus::ConfigureLexicalVarMode(int script_context_index,
int context_slot_index) {
DCHECK_LE(0, script_context_index);
DCHECK_LE(0, context_slot_index);
if (!ContextIndexBits::is_valid(script_context_index) ||
!SlotIndexBits::is_valid(context_slot_index)) {
return false;
}
int config = ContextIndexBits::encode(script_context_index) |
SlotIndexBits::encode(context_slot_index);
SetFeedback(Smi::FromInt(config));
Isolate* isolate = GetIsolate();
SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
SKIP_WRITE_BARRIER);
return true;
}
void GlobalICNexus::ConfigureHandlerMode(Handle<Object> handler) {
SetFeedback(GetIsolate()->heap()->empty_weak_cell()); SetFeedback(GetIsolate()->heap()->empty_weak_cell());
SetFeedbackExtra(*handler); SetFeedbackExtra(*handler);
} }
InlineCacheState StoreGlobalICNexus::StateFromFeedback() const { InlineCacheState GlobalICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate(); Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback(); Object* feedback = GetFeedback();
if (feedback->IsSmi()) return MONOMORPHIC;
Object* extra = GetFeedbackExtra(); Object* extra = GetFeedbackExtra();
if (!WeakCell::cast(feedback)->cleared() || if (!WeakCell::cast(feedback)->cleared() ||
...@@ -752,25 +759,6 @@ void CallICNexus::ConfigureUninitialized() { ...@@ -752,25 +759,6 @@ void CallICNexus::ConfigureUninitialized() {
SetFeedbackExtra(Smi::kZero, SKIP_WRITE_BARRIER); SetFeedbackExtra(Smi::kZero, SKIP_WRITE_BARRIER);
} }
void LoadGlobalICNexus::ConfigureUninitialized() {
Isolate* isolate = GetIsolate();
SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
SKIP_WRITE_BARRIER);
}
void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
Isolate* isolate = GetIsolate();
SetFeedback(*isolate->factory()->NewWeakCell(cell));
SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
SKIP_WRITE_BARRIER);
}
void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Object> handler) {
SetFeedback(GetIsolate()->heap()->empty_weak_cell());
SetFeedbackExtra(*handler);
}
void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name, void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name,
Handle<Map> receiver_map, Handle<Map> receiver_map,
Handle<Object> handler) { Handle<Object> handler) {
......
...@@ -90,6 +90,10 @@ inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) { ...@@ -90,6 +90,10 @@ inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
kind == FeedbackSlotKind::kStoreKeyedStrict; kind == FeedbackSlotKind::kStoreKeyedStrict;
} }
inline bool IsGlobalICKind(FeedbackSlotKind kind) {
return IsLoadGlobalICKind(kind) || IsStoreGlobalICKind(kind);
}
inline bool IsTypeProfileKind(FeedbackSlotKind kind) { inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
return kind == FeedbackSlotKind::kTypeProfile; return kind == FeedbackSlotKind::kTypeProfile;
} }
...@@ -208,6 +212,7 @@ class FeedbackVector : public HeapObject { ...@@ -208,6 +212,7 @@ class FeedbackVector : public HeapObject {
bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); } bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
DEFINE_SLOT_KIND_PREDICATE(IsCallIC) DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
DEFINE_SLOT_KIND_PREDICATE(IsGlobalIC)
DEFINE_SLOT_KIND_PREDICATE(IsLoadIC) DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC) DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC) DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
...@@ -676,35 +681,6 @@ class LoadICNexus : public FeedbackNexus { ...@@ -676,35 +681,6 @@ class LoadICNexus : public FeedbackNexus {
InlineCacheState StateFromFeedback() const override; InlineCacheState StateFromFeedback() const override;
}; };
class LoadGlobalICNexus : public FeedbackNexus {
public:
LoadGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) {
DCHECK(vector->IsLoadGlobalIC(slot));
}
LoadGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) {
DCHECK(vector->IsLoadGlobalIC(slot));
}
int ExtractMaps(MapHandles* maps) const final {
// LoadGlobalICs don't record map feedback.
return 0;
}
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
return MaybeHandle<Code>();
}
bool FindHandlers(ObjectHandles* code_list, int length = -1) const final {
return length == 0;
}
void ConfigureUninitialized() override;
void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
void ConfigureHandlerMode(Handle<Object> handler);
InlineCacheState StateFromFeedback() const override;
};
class KeyedLoadICNexus : public FeedbackNexus { class KeyedLoadICNexus : public FeedbackNexus {
public: public:
KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
...@@ -740,19 +716,20 @@ class StoreICNexus : public FeedbackNexus { ...@@ -740,19 +716,20 @@ class StoreICNexus : public FeedbackNexus {
InlineCacheState StateFromFeedback() const override; InlineCacheState StateFromFeedback() const override;
}; };
class StoreGlobalICNexus : public FeedbackNexus { // Base class for LoadGlobalICNexus and StoreGlobalICNexus.
class GlobalICNexus : public FeedbackNexus {
public: public:
StoreGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) GlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) { : FeedbackNexus(vector, slot) {
DCHECK(vector->IsStoreGlobalIC(slot)); DCHECK(vector->IsGlobalIC(slot));
} }
StoreGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot) GlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
: FeedbackNexus(vector, slot) { : FeedbackNexus(vector, slot) {
DCHECK(vector->IsStoreGlobalIC(slot)); DCHECK(vector->IsGlobalIC(slot));
} }
int ExtractMaps(MapHandles* maps) const final { int ExtractMaps(MapHandles* maps) const final {
// StoreGlobalICs don't record map feedback. // Load/StoreGlobalICs don't record map feedback.
return 0; return 0;
} }
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final { MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
...@@ -764,9 +741,47 @@ class StoreGlobalICNexus : public FeedbackNexus { ...@@ -764,9 +741,47 @@ class StoreGlobalICNexus : public FeedbackNexus {
void ConfigureUninitialized() override; void ConfigureUninitialized() override;
void ConfigurePropertyCellMode(Handle<PropertyCell> cell); void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
// Returns false if given combination of indices is not allowed.
bool ConfigureLexicalVarMode(int script_context_index,
int context_slot_index);
void ConfigureHandlerMode(Handle<Object> handler); void ConfigureHandlerMode(Handle<Object> handler);
InlineCacheState StateFromFeedback() const override; InlineCacheState StateFromFeedback() const override;
// Bit positions in a smi that encodes lexical environment variable access.
#define LEXICAL_MODE_BIT_FIELDS(V, _) \
V(ContextIndexBits, unsigned, 12, _) \
V(SlotIndexBits, unsigned, 19, _)
DEFINE_BIT_FIELDS(LEXICAL_MODE_BIT_FIELDS)
#undef LEXICAL_MODE_BIT_FIELDS
// Make sure we don't overflow the smi.
STATIC_ASSERT(LEXICAL_MODE_BIT_FIELDS_Ranges::kBitsCount <= kSmiValueSize);
};
class LoadGlobalICNexus : public GlobalICNexus {
public:
LoadGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
: GlobalICNexus(vector, slot) {
DCHECK(vector->IsLoadGlobalIC(slot));
}
LoadGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
: GlobalICNexus(vector, slot) {
DCHECK(vector->IsLoadGlobalIC(slot));
}
};
class StoreGlobalICNexus : public GlobalICNexus {
public:
StoreGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
: GlobalICNexus(vector, slot) {
DCHECK(vector->IsStoreGlobalIC(slot));
}
StoreGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot)
: GlobalICNexus(vector, slot) {
DCHECK(vector->IsStoreGlobalIC(slot));
}
}; };
// TODO(ishell): Currently we use StoreOwnIC only for storing properties that // TODO(ishell): Currently we use StoreOwnIC only for storing properties that
......
...@@ -2309,20 +2309,41 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) { ...@@ -2309,20 +2309,41 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
} }
void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase( void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler, SloppyTNode<Context> context, Node* vector, Node* slot,
Label* miss, ParameterMode slot_mode) { ExitPoint* exit_point, Label* try_handler, Label* miss,
ParameterMode slot_mode) {
Comment("LoadGlobalIC_TryPropertyCellCase"); Comment("LoadGlobalIC_TryPropertyCellCase");
Node* weak_cell = LoadFeedbackVectorSlot(vector, slot, 0, slot_mode); Label if_lexical_var(this), if_property_cell(this);
CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE)); Node* maybe_weak_cell = LoadFeedbackVectorSlot(vector, slot, 0, slot_mode);
Branch(TaggedIsSmi(maybe_weak_cell), &if_lexical_var, &if_property_cell);
// Load value or try handler case if the {weak_cell} is cleared. BIND(&if_property_cell);
Node* property_cell = LoadWeakCellValue(weak_cell, try_handler); {
CSA_ASSERT(this, IsPropertyCell(property_cell)); Node* weak_cell = maybe_weak_cell;
CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE));
Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset); // Load value or try handler case if the {weak_cell} is cleared.
GotoIf(WordEqual(value, TheHoleConstant()), miss); Node* property_cell = LoadWeakCellValue(weak_cell, try_handler);
exit_point->Return(value); CSA_ASSERT(this, IsPropertyCell(property_cell));
Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset);
GotoIf(WordEqual(value, TheHoleConstant()), miss);
exit_point->Return(value);
}
BIND(&if_lexical_var);
{
Comment("Load lexical variable");
TNode<IntPtrT> lexical_handler = SmiUntag(maybe_weak_cell);
TNode<IntPtrT> context_index =
Signed(DecodeWord<GlobalICNexus::ContextIndexBits>(lexical_handler));
TNode<IntPtrT> slot_index =
Signed(DecodeWord<GlobalICNexus::SlotIndexBits>(lexical_handler));
TNode<Context> script_context = LoadScriptContext(context, context_index);
TNode<Object> result = LoadContextElement(script_context, slot_index);
exit_point->Return(result);
}
} }
void AccessorAssembler::LoadGlobalIC_TryHandlerCase(const LoadICParameters* pp, void AccessorAssembler::LoadGlobalIC_TryHandlerCase(const LoadICParameters* pp,
...@@ -2388,7 +2409,7 @@ void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, ...@@ -2388,7 +2409,7 @@ void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p,
ExitPoint direct_exit(this); ExitPoint direct_exit(this);
Label try_handler(this), miss(this); Label try_handler(this), miss(this);
LoadGlobalIC_TryPropertyCellCase(p->vector, p->slot, &direct_exit, LoadGlobalIC_TryPropertyCellCase(p->context, p->vector, p->slot, &direct_exit,
&try_handler, &miss); &try_handler, &miss);
BIND(&try_handler); BIND(&try_handler);
...@@ -2657,37 +2678,57 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) { ...@@ -2657,37 +2678,57 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
} }
void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) { void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
Label try_handler(this), miss(this, Label::kDeferred); Label if_lexical_var(this), if_property_cell(this);
Node* maybe_weak_cell =
Node* feedback =
LoadFeedbackVectorSlot(pp->vector, pp->slot, 0, SMI_PARAMETERS); LoadFeedbackVectorSlot(pp->vector, pp->slot, 0, SMI_PARAMETERS);
Node* property_cell = LoadWeakCellValue(feedback, &try_handler); Branch(TaggedIsSmi(maybe_weak_cell), &if_lexical_var, &if_property_cell);
ExitPoint direct_exit(this); BIND(&if_property_cell);
StoreGlobalIC_PropertyCellCase(property_cell, pp->value, &direct_exit, &miss);
BIND(&try_handler);
{ {
Comment("StoreGlobalIC_try_handler"); Label try_handler(this), miss(this, Label::kDeferred);
Node* handler = LoadFeedbackVectorSlot(pp->vector, pp->slot, kPointerSize, Node* property_cell = LoadWeakCellValue(maybe_weak_cell, &try_handler);
SMI_PARAMETERS);
GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)), ExitPoint direct_exit(this);
&miss); StoreGlobalIC_PropertyCellCase(property_cell, pp->value, &direct_exit,
&miss);
StoreICParameters p = *pp; BIND(&try_handler);
DCHECK_NULL(p.receiver); {
Node* native_context = LoadNativeContext(p.context); Comment("StoreGlobalIC_try_handler");
p.receiver = Node* handler = LoadFeedbackVectorSlot(pp->vector, pp->slot, kPointerSize,
LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX); SMI_PARAMETERS);
GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
&miss);
StoreICParameters p = *pp;
DCHECK_NULL(p.receiver);
Node* native_context = LoadNativeContext(p.context);
p.receiver =
LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX);
HandleStoreICHandlerCase(&p, handler, &miss, ICMode::kGlobalIC);
}
HandleStoreICHandlerCase(&p, handler, &miss, ICMode::kGlobalIC); BIND(&miss);
{
TailCallRuntime(Runtime::kStoreGlobalIC_Miss, pp->context, pp->value,
pp->slot, pp->vector, pp->name);
}
} }
BIND(&miss); BIND(&if_lexical_var);
{ {
TailCallRuntime(Runtime::kStoreGlobalIC_Miss, pp->context, pp->value, Comment("Store lexical variable");
pp->slot, pp->vector, pp->name); TNode<IntPtrT> lexical_handler = SmiUntag(maybe_weak_cell);
TNode<IntPtrT> context_index =
Signed(DecodeWord<GlobalICNexus::ContextIndexBits>(lexical_handler));
TNode<IntPtrT> slot_index =
Signed(DecodeWord<GlobalICNexus::SlotIndexBits>(lexical_handler));
TNode<Context> script_context =
LoadScriptContext(CAST(pp->context), context_index);
StoreContextElement(script_context, slot_index, CAST(pp->value));
Return(pp->value);
} }
} }
......
...@@ -71,8 +71,9 @@ class AccessorAssembler : public CodeStubAssembler { ...@@ -71,8 +71,9 @@ class AccessorAssembler : public CodeStubAssembler {
}; };
void LoadGlobalIC_TryPropertyCellCase( void LoadGlobalIC_TryPropertyCellCase(
Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler, SloppyTNode<Context> context, Node* vector, Node* slot,
Label* miss, ParameterMode slot_mode = SMI_PARAMETERS); ExitPoint* exit_point, Label* try_handler, Label* miss,
ParameterMode slot_mode = SMI_PARAMETERS);
void LoadGlobalIC_TryHandlerCase(const LoadICParameters* p, void LoadGlobalIC_TryHandlerCase(const LoadICParameters* p,
TypeofMode typeof_mode, TypeofMode typeof_mode,
ExitPoint* exit_point, Label* miss); ExitPoint* exit_point, Label* miss);
......
...@@ -491,10 +491,16 @@ MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) { ...@@ -491,10 +491,16 @@ MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
return ReferenceError(name); return ReferenceError(name);
} }
if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) { if (FLAG_use_ic) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub); LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
LoadScriptContextFieldStub stub(isolate(), &lookup_result); if (nexus->ConfigureLexicalVarMode(lookup_result.context_index,
PatchCache(name, stub.GetCode()); lookup_result.slot_index)) {
TRACE_HANDLER_STATS(isolate(), LoadGlobalIC_LoadScriptContextField);
} else {
// Given combination of indices can't be encoded, so use slow stub.
TRACE_HANDLER_STATS(isolate(), LoadGlobalIC_SlowStub);
PatchCache(name, slow_stub());
}
TRACE_IC("LoadGlobalIC", name); TRACE_IC("LoadGlobalIC", name);
} }
return result; return result;
...@@ -1315,10 +1321,17 @@ MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name, ...@@ -1315,10 +1321,17 @@ MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name,
return ReferenceError(name); return ReferenceError(name);
} }
if (FLAG_use_ic && StoreScriptContextFieldStub::Accepted(&lookup_result)) { if (FLAG_use_ic) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub); StoreGlobalICNexus* nexus = casted_nexus<StoreGlobalICNexus>();
StoreScriptContextFieldStub stub(isolate(), &lookup_result); if (nexus->ConfigureLexicalVarMode(lookup_result.context_index,
PatchCache(name, stub.GetCode()); lookup_result.slot_index)) {
TRACE_HANDLER_STATS(isolate(), StoreGlobalIC_StoreScriptContextField);
} else {
// Given combination of indices can't be encoded, so use slow stub.
TRACE_HANDLER_STATS(isolate(), StoreGlobalIC_SlowStub);
PatchCache(name, slow_stub());
}
TRACE_IC("StoreGlobalIC", name);
} }
script_context->set(lookup_result.slot_index, *value); script_context->set(lookup_result.slot_index, *value);
......
...@@ -175,8 +175,8 @@ class InterpreterLoadGlobalAssembler : public InterpreterAssembler { ...@@ -175,8 +175,8 @@ class InterpreterLoadGlobalAssembler : public InterpreterAssembler {
ExitPoint exit_point(this, &done, &var_result); ExitPoint exit_point(this, &done, &var_result);
accessor_asm.LoadGlobalIC_TryPropertyCellCase( accessor_asm.LoadGlobalIC_TryPropertyCellCase(
feedback_vector, feedback_slot, &exit_point, &try_handler, &miss, GetContext(), feedback_vector, feedback_slot, &exit_point,
CodeStubAssembler::INTPTR_PARAMETERS); &try_handler, &miss, CodeStubAssembler::INTPTR_PARAMETERS);
BIND(&done); BIND(&done);
SetAccumulator(var_result.value()); SetAccumulator(var_result.value());
......
...@@ -384,9 +384,9 @@ class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { }; ...@@ -384,9 +384,9 @@ class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
#define DEFINE_BIT_FIELD_RANGE_TYPE(Name, Type, Size, _) \ #define DEFINE_BIT_FIELD_RANGE_TYPE(Name, Type, Size, _) \
k##Name##Start, k##Name##End = k##Name##Start + Size - 1, k##Name##Start, k##Name##End = k##Name##Start + Size - 1,
#define DEFINE_BIT_RANGES(LIST_MACRO) \ #define DEFINE_BIT_RANGES(LIST_MACRO) \
struct LIST_MACRO##_Ranges { \ struct LIST_MACRO##_Ranges { \
enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) }; \ enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) kBitsCount }; \
}; };
#define DEFINE_BIT_FIELD_TYPE(Name, Type, Size, RangesName) \ #define DEFINE_BIT_FIELD_TYPE(Name, Type, Size, RangesName) \
......
...@@ -237,8 +237,8 @@ TEST(DecodeWordFromWord32) { ...@@ -237,8 +237,8 @@ TEST(DecodeWordFromWord32) {
CodeStubAssembler m(asm_tester.state()); CodeStubAssembler m(asm_tester.state());
class TestBitField : public BitField<unsigned, 3, 3> {}; class TestBitField : public BitField<unsigned, 3, 3> {};
m.Return( m.Return(m.SmiTag(
m.SmiTag(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2F)))); m.Signed(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2F)))));
FunctionTester ft(asm_tester.GenerateCode()); FunctionTester ft(asm_tester.GenerateCode());
MaybeHandle<Object> result = ft.Call(); MaybeHandle<Object> result = ft.Call();
// value = 00101111 // value = 00101111
......
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