Skip to content

Commit f87286e

Browse files
isheludkoCommit bot
authored andcommitted
Loads and stores to global vars are now made via property cell shortcuts installed into parent script context.
This CL also adds hydrogen stubs for global loads and global stores, full-codegen and TurboFan now uses this machinery. Review URL: https://codereview.chromium.org/1224793002 Cr-Commit-Position: refs/heads/master@{#29592}
1 parent a0129a2 commit f87286e

40 files changed

Lines changed: 1192 additions & 153 deletions

src/arm/full-codegen-arm.cc

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,13 +1492,30 @@ void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
14921492
Variable* var = proxy->var();
14931493
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
14941494
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
1495-
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
1496-
__ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
1497-
__ mov(LoadDescriptor::SlotRegister(),
1498-
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
1499-
// Inside typeof use a regular load, not a contextual load, to avoid
1500-
// a reference error.
1501-
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
1495+
if (var->IsGlobalSlot()) {
1496+
DCHECK(var->index() > 0);
1497+
DCHECK(var->IsStaticGlobalObjectProperty());
1498+
// Each var occupies two slots in the context: for reads and writes.
1499+
int slot_index = var->index();
1500+
int depth = scope()->ContextChainLength(var->scope());
1501+
__ mov(LoadGlobalViaContextDescriptor::DepthRegister(),
1502+
Operand(Smi::FromInt(depth)));
1503+
__ mov(LoadGlobalViaContextDescriptor::SlotRegister(),
1504+
Operand(Smi::FromInt(slot_index)));
1505+
__ mov(LoadGlobalViaContextDescriptor::NameRegister(),
1506+
Operand(var->name()));
1507+
LoadGlobalViaContextStub stub(isolate(), depth);
1508+
__ CallStub(&stub);
1509+
1510+
} else {
1511+
__ ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectOperand());
1512+
__ mov(LoadDescriptor::NameRegister(), Operand(var->name()));
1513+
__ mov(LoadDescriptor::SlotRegister(),
1514+
Operand(SmiFromSlot(proxy->VariableFeedbackSlot())));
1515+
// Inside typeof use a regular load, not a contextual load, to avoid
1516+
// a reference error.
1517+
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
1518+
}
15021519
}
15031520

15041521

@@ -2753,13 +2770,30 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
27532770

27542771
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
27552772
FeedbackVectorICSlot slot) {
2756-
if (var->IsUnallocatedOrGlobalSlot()) {
2773+
if (var->IsUnallocated()) {
27572774
// Global var, const, or let.
27582775
__ mov(StoreDescriptor::NameRegister(), Operand(var->name()));
27592776
__ ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectOperand());
27602777
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
27612778
CallStoreIC();
27622779

2780+
} else if (var->IsGlobalSlot()) {
2781+
// Global var, const, or let.
2782+
DCHECK(var->index() > 0);
2783+
DCHECK(var->IsStaticGlobalObjectProperty());
2784+
// Each var occupies two slots in the context: for reads and writes.
2785+
int slot_index = var->index() + 1;
2786+
int depth = scope()->ContextChainLength(var->scope());
2787+
__ mov(StoreGlobalViaContextDescriptor::DepthRegister(),
2788+
Operand(Smi::FromInt(depth)));
2789+
__ mov(StoreGlobalViaContextDescriptor::SlotRegister(),
2790+
Operand(Smi::FromInt(slot_index)));
2791+
__ mov(StoreGlobalViaContextDescriptor::NameRegister(),
2792+
Operand(var->name()));
2793+
DCHECK(StoreGlobalViaContextDescriptor::ValueRegister().is(r0));
2794+
StoreGlobalViaContextStub stub(isolate(), depth, language_mode());
2795+
__ CallStub(&stub);
2796+
27632797
} else if (var->mode() == LET && op != Token::INIT_LET) {
27642798
// Non-initializing assignment to let variable needs a write barrier.
27652799
DCHECK(!var->IsLookupSlot());

src/arm/interface-descriptors-arm.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ const Register VectorStoreICDescriptor::VectorRegister() { return r3; }
3636
const Register StoreTransitionDescriptor::MapRegister() { return r3; }
3737

3838

39+
const Register LoadGlobalViaContextDescriptor::DepthRegister() { return r1; }
40+
const Register LoadGlobalViaContextDescriptor::SlotRegister() { return r2; }
41+
const Register LoadGlobalViaContextDescriptor::NameRegister() { return r3; }
42+
43+
44+
const Register StoreGlobalViaContextDescriptor::DepthRegister() { return r1; }
45+
const Register StoreGlobalViaContextDescriptor::SlotRegister() { return r2; }
46+
const Register StoreGlobalViaContextDescriptor::NameRegister() { return r3; }
47+
const Register StoreGlobalViaContextDescriptor::ValueRegister() { return r0; }
48+
49+
3950
const Register ElementTransitionAndStoreDescriptor::MapRegister() { return r3; }
4051

4152

src/arm64/full-codegen-arm64.cc

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,13 +1472,30 @@ void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
14721472
Variable* var = proxy->var();
14731473
DCHECK(var->IsUnallocatedOrGlobalSlot() ||
14741474
(var->IsLookupSlot() && var->mode() == DYNAMIC_GLOBAL));
1475-
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
1476-
__ Mov(LoadDescriptor::NameRegister(), Operand(var->name()));
1477-
__ Mov(LoadDescriptor::SlotRegister(),
1478-
SmiFromSlot(proxy->VariableFeedbackSlot()));
1479-
// Inside typeof use a regular load, not a contextual load, to avoid
1480-
// a reference error.
1481-
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
1475+
if (var->IsGlobalSlot()) {
1476+
DCHECK(var->index() > 0);
1477+
DCHECK(var->IsStaticGlobalObjectProperty());
1478+
// Each var occupies two slots in the context: for reads and writes.
1479+
int slot_index = var->index();
1480+
int depth = scope()->ContextChainLength(var->scope());
1481+
__ Mov(LoadGlobalViaContextDescriptor::DepthRegister(),
1482+
Operand(Smi::FromInt(depth)));
1483+
__ Mov(LoadGlobalViaContextDescriptor::SlotRegister(),
1484+
Operand(Smi::FromInt(slot_index)));
1485+
__ Mov(LoadGlobalViaContextDescriptor::NameRegister(),
1486+
Operand(var->name()));
1487+
LoadGlobalViaContextStub stub(isolate(), depth);
1488+
__ CallStub(&stub);
1489+
1490+
} else {
1491+
__ Ldr(LoadDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
1492+
__ Mov(LoadDescriptor::NameRegister(), Operand(var->name()));
1493+
__ Mov(LoadDescriptor::SlotRegister(),
1494+
SmiFromSlot(proxy->VariableFeedbackSlot()));
1495+
// Inside typeof use a regular load, not a contextual load, to avoid
1496+
// a reference error.
1497+
CallLoadIC(typeof_state == NOT_INSIDE_TYPEOF ? CONTEXTUAL : NOT_CONTEXTUAL);
1498+
}
14821499
}
14831500

14841501

@@ -2439,13 +2456,30 @@ void FullCodeGenerator::EmitStoreToStackLocalOrContextSlot(
24392456
void FullCodeGenerator::EmitVariableAssignment(Variable* var, Token::Value op,
24402457
FeedbackVectorICSlot slot) {
24412458
ASM_LOCATION("FullCodeGenerator::EmitVariableAssignment");
2442-
if (var->IsUnallocatedOrGlobalSlot()) {
2459+
if (var->IsUnallocated()) {
24432460
// Global var, const, or let.
24442461
__ Mov(StoreDescriptor::NameRegister(), Operand(var->name()));
24452462
__ Ldr(StoreDescriptor::ReceiverRegister(), GlobalObjectMemOperand());
24462463
if (FLAG_vector_stores) EmitLoadStoreICSlot(slot);
24472464
CallStoreIC();
24482465

2466+
} else if (var->IsGlobalSlot()) {
2467+
// Global var, const, or let.
2468+
DCHECK(var->index() > 0);
2469+
DCHECK(var->IsStaticGlobalObjectProperty());
2470+
// Each var occupies two slots in the context: for reads and writes.
2471+
int slot_index = var->index() + 1;
2472+
int depth = scope()->ContextChainLength(var->scope());
2473+
__ Mov(StoreGlobalViaContextDescriptor::DepthRegister(),
2474+
Operand(Smi::FromInt(depth)));
2475+
__ Mov(StoreGlobalViaContextDescriptor::SlotRegister(),
2476+
Operand(Smi::FromInt(slot_index)));
2477+
__ Mov(StoreGlobalViaContextDescriptor::NameRegister(),
2478+
Operand(var->name()));
2479+
DCHECK(StoreGlobalViaContextDescriptor::ValueRegister().is(x0));
2480+
StoreGlobalViaContextStub stub(isolate(), depth, language_mode());
2481+
__ CallStub(&stub);
2482+
24492483
} else if (var->mode() == LET && op != Token::INIT_LET) {
24502484
// Non-initializing assignment to let variable needs a write barrier.
24512485
DCHECK(!var->IsLookupSlot());

src/arm64/interface-descriptors-arm64.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,17 @@ const Register VectorStoreICDescriptor::VectorRegister() { return x3; }
3636
const Register StoreTransitionDescriptor::MapRegister() { return x3; }
3737

3838

39+
const Register LoadGlobalViaContextDescriptor::DepthRegister() { return x1; }
40+
const Register LoadGlobalViaContextDescriptor::SlotRegister() { return x2; }
41+
const Register LoadGlobalViaContextDescriptor::NameRegister() { return x3; }
42+
43+
44+
const Register StoreGlobalViaContextDescriptor::DepthRegister() { return x1; }
45+
const Register StoreGlobalViaContextDescriptor::SlotRegister() { return x2; }
46+
const Register StoreGlobalViaContextDescriptor::NameRegister() { return x3; }
47+
const Register StoreGlobalViaContextDescriptor::ValueRegister() { return x0; }
48+
49+
3950
const Register ElementTransitionAndStoreDescriptor::MapRegister() { return x3; }
4051

4152

src/ast.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void VariableProxy::BindTo(Variable* var) {
9595
void VariableProxy::SetFirstFeedbackICSlot(FeedbackVectorICSlot slot,
9696
ICSlotCache* cache) {
9797
variable_feedback_slot_ = slot;
98-
if (var()->IsUnallocatedOrGlobalSlot()) {
98+
if (var()->IsUnallocated()) {
9999
cache->Add(VariableICSlotPair(var(), slot));
100100
}
101101
}
@@ -106,7 +106,7 @@ FeedbackVectorRequirements VariableProxy::ComputeFeedbackRequirements(
106106
if (UsesVariableFeedbackSlot()) {
107107
// VariableProxies that point to the same Variable within a function can
108108
// make their loads from the same IC slot.
109-
if (var()->IsUnallocatedOrGlobalSlot()) {
109+
if (var()->IsUnallocated()) {
110110
for (int i = 0; i < cache->length(); i++) {
111111
VariableICSlotPair& pair = cache->at(i);
112112
if (pair.variable() == var()) {
@@ -127,7 +127,7 @@ static int GetStoreICSlots(Expression* expr) {
127127
Property* property = expr->AsProperty();
128128
LhsKind assign_type = Property::GetAssignType(property);
129129
if ((assign_type == VARIABLE &&
130-
expr->AsVariableProxy()->var()->IsUnallocatedOrGlobalSlot()) ||
130+
expr->AsVariableProxy()->var()->IsUnallocated()) ||
131131
assign_type == NAMED_PROPERTY || assign_type == KEYED_PROPERTY) {
132132
ic_slots++;
133133
}
@@ -289,8 +289,7 @@ FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements(
289289
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
290290
}
291291

292-
if (scope() != NULL &&
293-
class_variable_proxy()->var()->IsUnallocatedOrGlobalSlot()) {
292+
if (scope() != NULL && class_variable_proxy()->var()->IsUnallocated()) {
294293
ic_slots++;
295294
}
296295

src/ast.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1667,7 +1667,7 @@ class VariableProxy final : public Expression {
16671667
void BindTo(Variable* var);
16681668

16691669
bool UsesVariableFeedbackSlot() const {
1670-
return var()->IsUnallocatedOrGlobalSlot() || var()->IsLookupSlot();
1670+
return var()->IsUnallocated() || var()->IsLookupSlot();
16711671
}
16721672

16731673
virtual FeedbackVectorRequirements ComputeFeedbackRequirements(

src/code-factory.cc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,21 @@ Callable CodeFactory::BinaryOpIC(Isolate* isolate, Token::Value op,
138138
}
139139

140140

141+
// static
142+
Callable CodeFactory::LoadGlobalViaContext(Isolate* isolate, int depth) {
143+
LoadGlobalViaContextStub stub(isolate, depth);
144+
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
145+
}
146+
147+
148+
// static
149+
Callable CodeFactory::StoreGlobalViaContext(Isolate* isolate, int depth,
150+
LanguageMode language_mode) {
151+
StoreGlobalViaContextStub stub(isolate, depth, language_mode);
152+
return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
153+
}
154+
155+
141156
// static
142157
Callable CodeFactory::Instanceof(Isolate* isolate,
143158
InstanceofStub::Flags flags) {

src/code-factory.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ class CodeFactory final {
6161

6262
// Code stubs. Add methods here as needed to reduce dependency on
6363
// code-stubs.h.
64+
static Callable LoadGlobalViaContext(Isolate* isolate, int depth);
65+
static Callable StoreGlobalViaContext(Isolate* isolate, int depth,
66+
LanguageMode language_mode);
67+
6468
static Callable Instanceof(Isolate* isolate, InstanceofStub::Flags flags);
6569

6670
static Callable ToBoolean(

0 commit comments

Comments
 (0)