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,
GotoIf(IsSetWord32(hash, Name::kDoesNotContainCachedArrayIndexMask),
&runtime);
var_result = SmiTag(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash));
var_result =
SmiTag(Signed(DecodeWordFromWord32<String::ArrayIndexValueBits>(hash)));
Goto(&end);
BIND(&runtime);
......@@ -5866,8 +5867,10 @@ TNode<Uint32T> CodeStubAssembler::DecodeWord32(SloppyTNode<Word32T> word32,
Word32And(word32, Int32Constant(mask)), static_cast<int>(shift)));
}
Node* CodeStubAssembler::DecodeWord(Node* word, uint32_t shift, uint32_t mask) {
return WordShr(WordAnd(word, IntPtrConstant(mask)), static_cast<int>(shift));
TNode<UintPtrT> CodeStubAssembler::DecodeWord(SloppyTNode<WordT> word,
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,
......@@ -7509,15 +7512,16 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key,
return var_result.value();
}
Node* CodeStubAssembler::LoadScriptContext(Node* context, int context_index) {
Node* native_context = LoadNativeContext(context);
Node* script_context_table =
LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX);
TNode<Context> CodeStubAssembler::LoadScriptContext(
TNode<Context> context, TNode<IntPtrT> context_index) {
TNode<Context> native_context = LoadNativeContext(context);
TNode<ScriptContextTable> script_context_table = CAST(
LoadContextElement(native_context, Context::SCRIPT_CONTEXT_TABLE_INDEX));
int offset =
ScriptContextTable::GetContextOffset(context_index) - kHeapObjectTag;
return Load(MachineType::AnyTagged(), script_context_table,
IntPtrConstant(offset));
Node* script_context = LoadFixedArrayElement(
script_context_table, context_index,
ScriptContextTable::kFirstContextSlotIndex * kPointerSize);
return CAST(script_context);
}
namespace {
......
......@@ -1248,22 +1248,23 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Returns a node that contains a decoded (unsigned!) value of a bit
// field |BitField| in |word|. Returns result as a word-size node.
template <typename BitField>
Node* DecodeWord(Node* word) {
TNode<UintPtrT> DecodeWord(SloppyTNode<WordT> word) {
return DecodeWord(word, BitField::kShift, BitField::kMask);
}
// Returns a node that contains a decoded (unsigned!) value of a bit
// field |BitField| in |word32|. Returns result as a word-size node.
template <typename BitField>
Node* DecodeWordFromWord32(Node* word32) {
TNode<UintPtrT> DecodeWordFromWord32(SloppyTNode<Word32T> word32) {
return DecodeWord<BitField>(ChangeUint32ToWord(word32));
}
// Returns a node that contains a decoded (unsigned!) value of a bit
// field |BitField| in |word|. Returns result as an uint32 node.
template <typename BitField>
Node* DecodeWord32FromWord(Node* word) {
return TruncateWordToWord32(DecodeWord<BitField>(word));
TNode<Uint32T> DecodeWord32FromWord(SloppyTNode<WordT> word) {
return UncheckedCast<Uint32T>(
TruncateWordToWord32(Signed(DecodeWord<BitField>(word))));
}
// Decodes an unsigned (!) value from |word32| to an uint32 node.
......@@ -1271,7 +1272,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
uint32_t mask);
// 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|.
template <typename BitField>
......@@ -1663,7 +1665,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
}
// 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* Float64ToUint8Clamped(Node* float64_value);
......
......@@ -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.
TF_STUB(StoreInterceptorStub, CodeStubAssembler) {
Node* receiver = Parameter(Descriptor::kReceiver);
......
......@@ -47,8 +47,6 @@ class Node;
V(ElementsTransitionAndStore) \
V(KeyedLoadSloppyArguments) \
V(KeyedStoreSloppyArguments) \
V(LoadScriptContextField) \
V(StoreScriptContextField) \
V(StringAdd) \
V(GetProperty) \
V(StoreFastElement) \
......@@ -793,59 +791,6 @@ class DoubleToIStub : public 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 {
public:
StoreFastElementStub(Isolate* isolate, bool is_js_array,
......
......@@ -1067,6 +1067,11 @@ class V8_EXPORT_PRIVATE CodeAssembler {
bool Word32ShiftIsSafe() const;
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;
// Calls respective callback registered in the state.
......
......@@ -24,10 +24,10 @@ ScriptContextTable* ScriptContextTable::cast(Object* 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) {
set(kUsedSlot, Smi::FromInt(used));
set(kUsedSlotIndex, Smi::FromInt(used));
}
......@@ -36,7 +36,7 @@ Handle<Context> ScriptContextTable::GetContext(Handle<ScriptContextTable> table,
int i) {
DCHECK(i < table->used());
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(
int used = table->used();
int length = table->length();
CHECK(used >= 0 && length > 0 && used < length);
if (used + kFirstContextSlot == length) {
if (used + kFirstContextSlotIndex == length) {
CHECK(length < Smi::kMaxValue / 2);
Isolate* isolate = table->GetIsolate();
Handle<FixedArray> copy =
......@@ -32,7 +32,7 @@ Handle<ScriptContextTable> ScriptContextTable::Extend(
result->set_used(used + 1);
DCHECK(script_context->IsScriptContext());
result->set(used + kFirstContextSlot, *script_context);
result->set(used + kFirstContextSlotIndex, *script_context);
return result;
}
......
......@@ -450,15 +450,8 @@ class ScriptContextTable : public FixedArray {
static Handle<ScriptContextTable> Extend(Handle<ScriptContextTable> table,
Handle<Context> script_context);
static int GetContextOffset(int context_index) {
return kFirstContextOffset + context_index * kPointerSize;
}
private:
static const int kUsedSlot = 0;
static const int kFirstContextSlot = kUsedSlot + 1;
static const int kFirstContextOffset =
FixedArray::kHeaderSize + kFirstContextSlot * kPointerSize;
static const int kUsedSlotIndex = 0;
static const int kFirstContextSlotIndex = 1;
DISALLOW_IMPLICIT_CONSTRUCTORS(ScriptContextTable);
};
......
......@@ -881,6 +881,8 @@ class RuntimeCallTimer final {
V(KeyedStoreIC_SlowStub) \
V(KeyedStoreIC_StoreFastElementStub) \
V(KeyedStoreIC_StoreElementStub) \
V(LoadGlobalIC_LoadScriptContextField) \
V(LoadGlobalIC_SlowStub) \
V(LoadIC_FunctionPrototypeStub) \
V(LoadIC_HandlerCacheHit_Accessor) \
V(LoadIC_LoadAccessorDH) \
......@@ -902,12 +904,13 @@ class RuntimeCallTimer final {
V(LoadIC_LoadNonexistentDH) \
V(LoadIC_LoadNormalDH) \
V(LoadIC_LoadNormalFromPrototypeDH) \
V(LoadIC_LoadScriptContextFieldStub) \
V(LoadIC_NonReceiver) \
V(LoadIC_Premonomorphic) \
V(LoadIC_SlowStub) \
V(LoadIC_StringLength) \
V(LoadIC_StringWrapperLength) \
V(StoreGlobalIC_StoreScriptContextField) \
V(StoreGlobalIC_SlowStub) \
V(StoreIC_HandlerCacheHit_Accessor) \
V(StoreIC_NonReceiver) \
V(StoreIC_Premonomorphic) \
......@@ -922,7 +925,6 @@ class RuntimeCallTimer final {
V(StoreIC_StoreNativeDataPropertyDH) \
V(StoreIC_StoreNativeDataPropertyOnPrototypeDH) \
V(StoreIC_StoreNormalDH) \
V(StoreIC_StoreScriptContextFieldStub) \
V(StoreIC_StoreTransitionDH)
enum RuntimeCallCounterId {
......
......@@ -579,18 +579,6 @@ InlineCacheState LoadICNexus::StateFromFeedback() const {
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 {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
......@@ -617,28 +605,47 @@ InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
return UNINITIALIZED;
}
void StoreGlobalICNexus::ConfigureUninitialized() {
void GlobalICNexus::ConfigureUninitialized() {
Isolate* isolate = GetIsolate();
SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
SKIP_WRITE_BARRIER);
}
void StoreGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
void GlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
Isolate* isolate = GetIsolate();
SetFeedback(*isolate->factory()->NewWeakCell(cell));
SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
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());
SetFeedbackExtra(*handler);
}
InlineCacheState StoreGlobalICNexus::StateFromFeedback() const {
InlineCacheState GlobalICNexus::StateFromFeedback() const {
Isolate* isolate = GetIsolate();
Object* feedback = GetFeedback();
if (feedback->IsSmi()) return MONOMORPHIC;
Object* extra = GetFeedbackExtra();
if (!WeakCell::cast(feedback)->cleared() ||
......@@ -752,25 +759,6 @@ void CallICNexus::ConfigureUninitialized() {
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,
Handle<Map> receiver_map,
Handle<Object> handler) {
......
......@@ -90,6 +90,10 @@ inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) {
kind == FeedbackSlotKind::kStoreKeyedStrict;
}
inline bool IsGlobalICKind(FeedbackSlotKind kind) {
return IsLoadGlobalICKind(kind) || IsStoreGlobalICKind(kind);
}
inline bool IsTypeProfileKind(FeedbackSlotKind kind) {
return kind == FeedbackSlotKind::kTypeProfile;
}
......@@ -208,6 +212,7 @@ class FeedbackVector : public HeapObject {
bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); }
DEFINE_SLOT_KIND_PREDICATE(IsCallIC)
DEFINE_SLOT_KIND_PREDICATE(IsGlobalIC)
DEFINE_SLOT_KIND_PREDICATE(IsLoadIC)
DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC)
DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC)
......@@ -676,35 +681,6 @@ class LoadICNexus : public FeedbackNexus {
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 {
public:
KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
......@@ -740,19 +716,20 @@ class StoreICNexus : public FeedbackNexus {
InlineCacheState StateFromFeedback() const override;
};
class StoreGlobalICNexus : public FeedbackNexus {
// Base class for LoadGlobalICNexus and StoreGlobalICNexus.
class GlobalICNexus : public FeedbackNexus {
public:
StoreGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot)
GlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot 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) {
DCHECK(vector->IsStoreGlobalIC(slot));
DCHECK(vector->IsGlobalIC(slot));
}
int ExtractMaps(MapHandles* maps) const final {
// StoreGlobalICs don't record map feedback.
// Load/StoreGlobalICs don't record map feedback.
return 0;
}
MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
......@@ -764,9 +741,47 @@ class StoreGlobalICNexus : public FeedbackNexus {
void ConfigureUninitialized() override;
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);
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
......
......@@ -2309,20 +2309,41 @@ void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) {
}
void AccessorAssembler::LoadGlobalIC_TryPropertyCellCase(
Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler,
Label* miss, ParameterMode slot_mode) {
SloppyTNode<Context> context, Node* vector, Node* slot,
ExitPoint* exit_point, Label* try_handler, Label* miss,
ParameterMode slot_mode) {
Comment("LoadGlobalIC_TryPropertyCellCase");
Node* weak_cell = LoadFeedbackVectorSlot(vector, slot, 0, slot_mode);
CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE));
Label if_lexical_var(this), if_property_cell(this);
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.
Node* property_cell = LoadWeakCellValue(weak_cell, try_handler);
CSA_ASSERT(this, IsPropertyCell(property_cell));
BIND(&if_property_cell);
{
Node* weak_cell = maybe_weak_cell;
CSA_ASSERT(this, HasInstanceType(weak_cell, WEAK_CELL_TYPE));
Node* value = LoadObjectField(property_cell, PropertyCell::kValueOffset);
GotoIf(WordEqual(value, TheHoleConstant()), miss);
exit_point->Return(value);
// Load value or try handler case if the {weak_cell} is cleared.
Node* property_cell = LoadWeakCellValue(weak_cell, try_handler);
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,
......@@ -2388,7 +2409,7 @@ void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p,
ExitPoint direct_exit(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);
BIND(&try_handler);
......@@ -2657,37 +2678,57 @@ void AccessorAssembler::StoreIC(const StoreICParameters* p) {
}
void AccessorAssembler::StoreGlobalIC(const StoreICParameters* pp) {
Label try_handler(this), miss(this, Label::kDeferred);
Node* feedback =
Label if_lexical_var(this), if_property_cell(this);
Node* maybe_weak_cell =
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);
StoreGlobalIC_PropertyCellCase(property_cell, pp->value, &direct_exit, &miss);
BIND(&try_handler);
BIND(&if_property_cell);
{
Comment("StoreGlobalIC_try_handler");
Node* handler = LoadFeedbackVectorSlot(pp->vector, pp->slot, kPointerSize,
SMI_PARAMETERS);
Label try_handler(this), miss(this, Label::kDeferred);
Node* property_cell = LoadWeakCellValue(maybe_weak_cell, &try_handler);
GotoIf(WordEqual(handler, LoadRoot(Heap::kuninitialized_symbolRootIndex)),
&miss);
ExitPoint direct_exit(this);
StoreGlobalIC_PropertyCellCase(property_cell, pp->value, &direct_exit,
&miss);
StoreICParameters p = *pp;
DCHECK_NULL(p.receiver);
Node* native_context = LoadNativeContext(p.context);
p.receiver =
LoadContextElement(native_context, Context::GLOBAL_PROXY_INDEX);
BIND(&try_handler);
{
Comment("StoreGlobalIC_try_handler");
Node* handler = LoadFeedbackVectorSlot(pp->vector, pp->slot, kPointerSize,
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,
pp->slot, pp->vector, pp->name);
Comment("Store 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(CAST(pp->context), context_index);
StoreContextElement(script_context, slot_index, CAST(pp->value));
Return(pp->value);
}
}
......
......@@ -71,8 +71,9 @@ class AccessorAssembler : public CodeStubAssembler {
};
void LoadGlobalIC_TryPropertyCellCase(
Node* vector, Node* slot, ExitPoint* exit_point, Label* try_handler,
Label* miss, ParameterMode slot_mode = SMI_PARAMETERS);
SloppyTNode<Context> context, Node* vector, Node* slot,
ExitPoint* exit_point, Label* try_handler, Label* miss,
ParameterMode slot_mode = SMI_PARAMETERS);
void LoadGlobalIC_TryHandlerCase(const LoadICParameters* p,
TypeofMode typeof_mode,
ExitPoint* exit_point, Label* miss);
......
......@@ -491,10 +491,16 @@ MaybeHandle<Object> LoadGlobalIC::Load(Handle<Name> name) {
return ReferenceError(name);
}
if (FLAG_use_ic && LoadScriptContextFieldStub::Accepted(&lookup_result)) {
TRACE_HANDLER_STATS(isolate(), LoadIC_LoadScriptContextFieldStub);
LoadScriptContextFieldStub stub(isolate(), &lookup_result);
PatchCache(name, stub.GetCode());
if (FLAG_use_ic) {
LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>();
if (nexus->ConfigureLexicalVarMode(lookup_result.context_index,
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);
}
return result;
......@@ -1315,10 +1321,17 @@ MaybeHandle<Object> StoreGlobalIC::Store(Handle<Name> name,
return ReferenceError(name);
}
if (FLAG_use_ic && StoreScriptContextFieldStub::Accepted(&lookup_result)) {
TRACE_HANDLER_STATS(isolate(), StoreIC_StoreScriptContextFieldStub);
StoreScriptContextFieldStub stub(isolate(), &lookup_result);
PatchCache(name, stub.GetCode());
if (FLAG_use_ic) {
StoreGlobalICNexus* nexus = casted_nexus<StoreGlobalICNexus>();
if (nexus->ConfigureLexicalVarMode(lookup_result.context_index,
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);
......
......@@ -175,8 +175,8 @@ class InterpreterLoadGlobalAssembler : public InterpreterAssembler {
ExitPoint exit_point(this, &done, &var_result);
accessor_asm.LoadGlobalIC_TryPropertyCellCase(
feedback_vector, feedback_slot, &exit_point, &try_handler, &miss,
CodeStubAssembler::INTPTR_PARAMETERS);
GetContext(), feedback_vector, feedback_slot, &exit_point,
&try_handler, &miss, CodeStubAssembler::INTPTR_PARAMETERS);
BIND(&done);
SetAccumulator(var_result.value());
......
......@@ -384,9 +384,9 @@ class BitField64 : public BitFieldBase<T, shift, size, uint64_t> { };
#define DEFINE_BIT_FIELD_RANGE_TYPE(Name, Type, Size, _) \
k##Name##Start, k##Name##End = k##Name##Start + Size - 1,
#define DEFINE_BIT_RANGES(LIST_MACRO) \
struct LIST_MACRO##_Ranges { \
enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) }; \
#define DEFINE_BIT_RANGES(LIST_MACRO) \
struct LIST_MACRO##_Ranges { \
enum { LIST_MACRO(DEFINE_BIT_FIELD_RANGE_TYPE, _) kBitsCount }; \
};
#define DEFINE_BIT_FIELD_TYPE(Name, Type, Size, RangesName) \
......
......@@ -237,8 +237,8 @@ TEST(DecodeWordFromWord32) {
CodeStubAssembler m(asm_tester.state());
class TestBitField : public BitField<unsigned, 3, 3> {};
m.Return(
m.SmiTag(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2F))));
m.Return(m.SmiTag(
m.Signed(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2F)))));
FunctionTester ft(asm_tester.GenerateCode());
MaybeHandle<Object> result = ft.Call();
// 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