Commit 17c8ffea authored by mvstanton's avatar mvstanton Committed by Commit bot

Vector ICs: Turbofan vector store ic support

Turbofan needs to pass vector slots around for named and keyed stores.
Also, the CL addresses a missing slot for ClassLiterals.

BUG=

Review URL: https://codereview.chromium.org/1178363002

Cr-Commit-Position: refs/heads/master@{#29173}
parent ed0bd594
...@@ -2550,7 +2550,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, ...@@ -2550,7 +2550,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
} }
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
// Constructor is in r0. // Constructor is in r0.
DCHECK(lit != NULL); DCHECK(lit != NULL);
__ push(r0); __ push(r0);
...@@ -2562,10 +2563,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2562,10 +2563,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset)); FieldMemOperand(r0, JSFunction::kPrototypeOrInitialMapOffset));
__ push(scratch); __ push(scratch);
// store_slot_index points to the vector IC slot for the next store IC used.
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (int i = 0; i < lit->properties()->length(); i++) { for (int i = 0; i < lit->properties()->length(); i++) {
ObjectLiteral::Property* property = lit->properties()->at(i); ObjectLiteral::Property* property = lit->properties()->at(i);
Expression* value = property->value(); Expression* value = property->value();
...@@ -2589,7 +2586,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2589,7 +2586,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2, EmitSetHomeObjectIfNeeded(value, 2,
lit->SlotForHomeObject(value, &store_slot_index)); lit->SlotForHomeObject(value, used_store_slots));
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
...@@ -2622,10 +2619,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2622,10 +2619,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// constructor // constructor
__ CallRuntime(Runtime::kToFastProperties, 1); __ CallRuntime(Runtime::kToFastProperties, 1);
// Verify that compilation exactly consumed the number of store ic slots that
// the ClassLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
} }
......
...@@ -2239,7 +2239,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) { ...@@ -2239,7 +2239,8 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
} }
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
// Constructor is in x0. // Constructor is in x0.
DCHECK(lit != NULL); DCHECK(lit != NULL);
__ push(x0); __ push(x0);
...@@ -2251,10 +2252,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2251,10 +2252,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
FieldMemOperand(x0, JSFunction::kPrototypeOrInitialMapOffset)); FieldMemOperand(x0, JSFunction::kPrototypeOrInitialMapOffset));
__ Push(scratch); __ Push(scratch);
// store_slot_index points to the vector IC slot for the next store IC used.
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (int i = 0; i < lit->properties()->length(); i++) { for (int i = 0; i < lit->properties()->length(); i++) {
ObjectLiteral::Property* property = lit->properties()->at(i); ObjectLiteral::Property* property = lit->properties()->at(i);
Expression* value = property->value(); Expression* value = property->value();
...@@ -2278,7 +2275,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2278,7 +2275,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2, EmitSetHomeObjectIfNeeded(value, 2,
lit->SlotForHomeObject(value, &store_slot_index)); lit->SlotForHomeObject(value, used_store_slots));
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
...@@ -2311,10 +2308,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2311,10 +2308,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// constructor // constructor
__ CallRuntime(Runtime::kToFastProperties, 1); __ CallRuntime(Runtime::kToFastProperties, 1);
// Verify that compilation exactly consumed the number of store ic slots that
// the ClassLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
} }
......
...@@ -289,6 +289,10 @@ FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements( ...@@ -289,6 +289,10 @@ FeedbackVectorRequirements ClassLiteral::ComputeFeedbackRequirements(
if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++; if (FunctionLiteral::NeedsHomeObject(value)) ic_slots++;
} }
if (scope() != NULL && class_variable_proxy()->var()->IsUnallocated()) {
ic_slots++;
}
#ifdef DEBUG #ifdef DEBUG
// FullCodeGenerator::VisitClassLiteral verifies that it consumes slot_count_ // FullCodeGenerator::VisitClassLiteral verifies that it consumes slot_count_
// slots. // slots.
......
This diff is collapsed.
...@@ -269,7 +269,9 @@ class AstGraphBuilder : public AstVisitor { ...@@ -269,7 +269,9 @@ class AstGraphBuilder : public AstVisitor {
// Builders for variable load and assignment. // Builders for variable load and assignment.
Node* BuildVariableAssignment(Variable* variable, Node* value, Node* BuildVariableAssignment(Variable* variable, Node* value,
Token::Value op, BailoutId bailout_id, Token::Value op,
const ResolvedFeedbackSlot& slot,
BailoutId bailout_id,
FrameStateBeforeAndAfter& states, FrameStateBeforeAndAfter& states,
OutputFrameStateCombine framestate_combine = OutputFrameStateCombine framestate_combine =
OutputFrameStateCombine::Ignore()); OutputFrameStateCombine::Ignore());
...@@ -288,8 +290,10 @@ class AstGraphBuilder : public AstVisitor { ...@@ -288,8 +290,10 @@ class AstGraphBuilder : public AstVisitor {
const ResolvedFeedbackSlot& feedback, const ResolvedFeedbackSlot& feedback,
ContextualMode mode = NOT_CONTEXTUAL); ContextualMode mode = NOT_CONTEXTUAL);
Node* BuildKeyedStore(Node* receiver, Node* key, Node* value, Node* BuildKeyedStore(Node* receiver, Node* key, Node* value,
const ResolvedFeedbackSlot& feedback,
TypeFeedbackId id); TypeFeedbackId id);
Node* BuildNamedStore(Node* receiver, Handle<Name>, Node* value, Node* BuildNamedStore(Node* receiver, Handle<Name>, Node* value,
const ResolvedFeedbackSlot& feedback,
TypeFeedbackId id); TypeFeedbackId id);
// Builders for super property loads and stores. // Builders for super property loads and stores.
...@@ -321,7 +325,8 @@ class AstGraphBuilder : public AstVisitor { ...@@ -321,7 +325,8 @@ class AstGraphBuilder : public AstVisitor {
// Builder for adding the [[HomeObject]] to a value if the value came from a // Builder for adding the [[HomeObject]] to a value if the value came from a
// function literal and needs a home object. Do nothing otherwise. // function literal and needs a home object. Do nothing otherwise.
Node* BuildSetHomeObject(Node* value, Node* home_object, Expression* expr); Node* BuildSetHomeObject(Node* value, Node* home_object, Expression* expr,
const ResolvedFeedbackSlot& slot);
// Builders for error reporting at runtime. // Builders for error reporting at runtime.
Node* BuildThrowError(Node* exception, BailoutId bailout_id); Node* BuildThrowError(Node* exception, BailoutId bailout_id);
...@@ -387,6 +392,7 @@ class AstGraphBuilder : public AstVisitor { ...@@ -387,6 +392,7 @@ class AstGraphBuilder : public AstVisitor {
// Dispatched from VisitForInStatement. // Dispatched from VisitForInStatement.
void VisitForInAssignment(Expression* expr, Node* value, void VisitForInAssignment(Expression* expr, Node* value,
const ResolvedFeedbackSlot& slot,
BailoutId bailout_id); BailoutId bailout_id);
// Dispatched from VisitClassLiteral. // Dispatched from VisitClassLiteral.
......
...@@ -248,7 +248,8 @@ const LoadNamedParameters& LoadNamedParametersOf(const Operator* op) { ...@@ -248,7 +248,8 @@ const LoadNamedParameters& LoadNamedParametersOf(const Operator* op) {
bool operator==(StoreNamedParameters const& lhs, bool operator==(StoreNamedParameters const& lhs,
StoreNamedParameters const& rhs) { StoreNamedParameters const& rhs) {
return lhs.language_mode() == rhs.language_mode() && lhs.name() == rhs.name(); return lhs.language_mode() == rhs.language_mode() &&
lhs.name() == rhs.name() && lhs.feedback() == rhs.feedback();
} }
...@@ -259,7 +260,7 @@ bool operator!=(StoreNamedParameters const& lhs, ...@@ -259,7 +260,7 @@ bool operator!=(StoreNamedParameters const& lhs,
size_t hash_value(StoreNamedParameters const& p) { size_t hash_value(StoreNamedParameters const& p) {
return base::hash_combine(p.language_mode(), p.name()); return base::hash_combine(p.language_mode(), p.name(), p.feedback());
} }
...@@ -274,6 +275,35 @@ const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) { ...@@ -274,6 +275,35 @@ const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
} }
bool operator==(StorePropertyParameters const& lhs,
StorePropertyParameters const& rhs) {
return lhs.language_mode() == rhs.language_mode() &&
lhs.feedback() == rhs.feedback();
}
bool operator!=(StorePropertyParameters const& lhs,
StorePropertyParameters const& rhs) {
return !(lhs == rhs);
}
size_t hash_value(StorePropertyParameters const& p) {
return base::hash_combine(p.language_mode(), p.feedback());
}
std::ostream& operator<<(std::ostream& os, StorePropertyParameters const& p) {
return os << p.language_mode();
}
const StorePropertyParameters& StorePropertyParametersOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kJSStoreProperty, op->opcode());
return OpParameter<StorePropertyParameters>(op);
}
bool operator==(CreateClosureParameters const& lhs, bool operator==(CreateClosureParameters const& lhs,
CreateClosureParameters const& rhs) { CreateClosureParameters const& rhs) {
return lhs.pretenure() == rhs.pretenure() && return lhs.pretenure() == rhs.pretenure() &&
...@@ -348,8 +378,7 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) { ...@@ -348,8 +378,7 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
V(Subtract, Operator::kNoProperties, 2, 1) \ V(Subtract, Operator::kNoProperties, 2, 1) \
V(Multiply, Operator::kNoProperties, 2, 1) \ V(Multiply, Operator::kNoProperties, 2, 1) \
V(Divide, Operator::kNoProperties, 2, 1) \ V(Divide, Operator::kNoProperties, 2, 1) \
V(Modulus, Operator::kNoProperties, 2, 1) \ V(Modulus, Operator::kNoProperties, 2, 1)
V(StoreProperty, Operator::kNoProperties, 3, 0)
struct JSOperatorGlobalCache final { struct JSOperatorGlobalCache final {
...@@ -480,9 +509,10 @@ const Operator* JSOperatorBuilder::LoadProperty( ...@@ -480,9 +509,10 @@ const Operator* JSOperatorBuilder::LoadProperty(
} }
const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode, const Operator* JSOperatorBuilder::StoreNamed(
const Unique<Name>& name) { LanguageMode language_mode, const Unique<Name>& name,
StoreNamedParameters parameters(language_mode, name); const ResolvedFeedbackSlot& feedback) {
StoreNamedParameters parameters(language_mode, feedback, name);
return new (zone()) Operator1<StoreNamedParameters>( // -- return new (zone()) Operator1<StoreNamedParameters>( // --
IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode
"JSStoreNamed", // name "JSStoreNamed", // name
...@@ -491,6 +521,17 @@ const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode, ...@@ -491,6 +521,17 @@ const Operator* JSOperatorBuilder::StoreNamed(LanguageMode language_mode,
} }
const Operator* JSOperatorBuilder::StoreProperty(
LanguageMode language_mode, const ResolvedFeedbackSlot& feedback) {
StorePropertyParameters parameters(language_mode, feedback);
return new (zone()) Operator1<StorePropertyParameters>( // --
IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode
"JSStoreProperty", // name
3, 1, 1, 0, 1, 2, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) { const Operator* JSOperatorBuilder::DeleteProperty(LanguageMode language_mode) {
return new (zone()) Operator1<LanguageMode>( // -- return new (zone()) Operator1<LanguageMode>( // --
IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode
......
...@@ -274,15 +274,19 @@ const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op); ...@@ -274,15 +274,19 @@ const LoadPropertyParameters& LoadPropertyParametersOf(const Operator* op);
// used as a parameter by JSStoreNamed operators. // used as a parameter by JSStoreNamed operators.
class StoreNamedParameters final { class StoreNamedParameters final {
public: public:
StoreNamedParameters(LanguageMode language_mode, const Unique<Name>& name) StoreNamedParameters(LanguageMode language_mode,
: language_mode_(language_mode), name_(name) {} const ResolvedFeedbackSlot& feedback,
const Unique<Name>& name)
: language_mode_(language_mode), name_(name), feedback_(feedback) {}
LanguageMode language_mode() const { return language_mode_; } LanguageMode language_mode() const { return language_mode_; }
const ResolvedFeedbackSlot& feedback() const { return feedback_; }
const Unique<Name>& name() const { return name_; } const Unique<Name>& name() const { return name_; }
private: private:
const LanguageMode language_mode_; const LanguageMode language_mode_;
const Unique<Name> name_; const Unique<Name> name_;
const ResolvedFeedbackSlot feedback_;
}; };
bool operator==(StoreNamedParameters const&, StoreNamedParameters const&); bool operator==(StoreNamedParameters const&, StoreNamedParameters const&);
...@@ -295,6 +299,32 @@ std::ostream& operator<<(std::ostream&, StoreNamedParameters const&); ...@@ -295,6 +299,32 @@ std::ostream& operator<<(std::ostream&, StoreNamedParameters const&);
const StoreNamedParameters& StoreNamedParametersOf(const Operator* op); const StoreNamedParameters& StoreNamedParametersOf(const Operator* op);
// Defines the property being stored to an object. This is used as a parameter
// by JSStoreProperty operators.
class StorePropertyParameters final {
public:
StorePropertyParameters(LanguageMode language_mode,
const ResolvedFeedbackSlot& feedback)
: language_mode_(language_mode), feedback_(feedback) {}
LanguageMode language_mode() const { return language_mode_; }
const ResolvedFeedbackSlot& feedback() const { return feedback_; }
private:
const LanguageMode language_mode_;
const ResolvedFeedbackSlot feedback_;
};
bool operator==(StorePropertyParameters const&, StorePropertyParameters const&);
bool operator!=(StorePropertyParameters const&, StorePropertyParameters const&);
size_t hash_value(StorePropertyParameters const&);
std::ostream& operator<<(std::ostream&, StorePropertyParameters const&);
const StorePropertyParameters& StorePropertyParametersOf(const Operator* op);
// Defines shared information for the closure that should be created. This is // Defines shared information for the closure that should be created. This is
// used as a parameter by JSCreateClosure operators. // used as a parameter by JSCreateClosure operators.
class CreateClosureParameters final { class CreateClosureParameters final {
...@@ -373,9 +403,11 @@ class JSOperatorBuilder final : public ZoneObject { ...@@ -373,9 +403,11 @@ class JSOperatorBuilder final : public ZoneObject {
const ResolvedFeedbackSlot& feedback, const ResolvedFeedbackSlot& feedback,
ContextualMode contextual_mode = NOT_CONTEXTUAL); ContextualMode contextual_mode = NOT_CONTEXTUAL);
const Operator* StoreProperty(LanguageMode language_mode); const Operator* StoreProperty(LanguageMode language_mode,
const ResolvedFeedbackSlot& feedback);
const Operator* StoreNamed(LanguageMode language_mode, const Operator* StoreNamed(LanguageMode language_mode,
const Unique<Name>& name); const Unique<Name>& name,
const ResolvedFeedbackSlot& feedback);
const Operator* DeleteProperty(LanguageMode language_mode); const Operator* DeleteProperty(LanguageMode language_mode);
......
...@@ -1424,13 +1424,22 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) { ...@@ -1424,13 +1424,22 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
__ CallRuntime(Runtime::kDefineClass, 6); __ CallRuntime(Runtime::kDefineClass, 6);
PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG); PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);
EmitClassDefineProperties(lit);
int store_slot_index = 0;
EmitClassDefineProperties(lit, &store_slot_index);
if (lit->scope() != NULL) { if (lit->scope() != NULL) {
DCHECK_NOT_NULL(lit->class_variable_proxy()); DCHECK_NOT_NULL(lit->class_variable_proxy());
FeedbackVectorICSlot slot = FLAG_vector_stores
? lit->GetNthSlot(store_slot_index++)
: FeedbackVectorICSlot::Invalid();
EmitVariableAssignment(lit->class_variable_proxy()->var(), EmitVariableAssignment(lit->class_variable_proxy()->var(),
Token::INIT_CONST); Token::INIT_CONST, slot);
} }
// Verify that compilation exactly consumed the number of store ic slots
// that the ClassLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
} }
context()->Plug(result_register()); context()->Plug(result_register());
......
...@@ -615,7 +615,7 @@ class FullCodeGenerator: public AstVisitor { ...@@ -615,7 +615,7 @@ class FullCodeGenerator: public AstVisitor {
// Adds the properties to the class (function) object and to its prototype. // Adds the properties to the class (function) object and to its prototype.
// Expects the class (function) in the accumulator. The class (function) is // Expects the class (function) in the accumulator. The class (function) is
// in the accumulator after installing all the properties. // in the accumulator after installing all the properties.
void EmitClassDefineProperties(ClassLiteral* lit); void EmitClassDefineProperties(ClassLiteral* lit, int* used_store_slots);
// Pushes the property key as a Name on the stack. // Pushes the property key as a Name on the stack.
void EmitPropertyKey(ObjectLiteralProperty* property, BailoutId bailout_id); void EmitPropertyKey(ObjectLiteralProperty* property, BailoutId bailout_id);
...@@ -634,14 +634,12 @@ class FullCodeGenerator: public AstVisitor { ...@@ -634,14 +634,12 @@ class FullCodeGenerator: public AstVisitor {
// Assign to the given expression as if via '='. The right-hand-side value // Assign to the given expression as if via '='. The right-hand-side value
// is expected in the accumulator. slot is only used if FLAG_vector_stores // is expected in the accumulator. slot is only used if FLAG_vector_stores
// is true. // is true.
void EmitAssignment(Expression* expr, FeedbackVectorICSlot slot = void EmitAssignment(Expression* expr, FeedbackVectorICSlot slot);
FeedbackVectorICSlot::Invalid());
// Complete a variable assignment. The right-hand-side value is expected // Complete a variable assignment. The right-hand-side value is expected
// in the accumulator. // in the accumulator.
void EmitVariableAssignment( void EmitVariableAssignment(Variable* var, Token::Value op,
Variable* var, Token::Value op, FeedbackVectorICSlot slot);
FeedbackVectorICSlot slot = FeedbackVectorICSlot::Invalid());
// Helper functions to EmitVariableAssignment // Helper functions to EmitVariableAssignment
void EmitStoreToStackLocalOrContextSlot(Variable* var, void EmitStoreToStackLocalOrContextSlot(Variable* var,
......
...@@ -2463,7 +2463,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, ...@@ -2463,7 +2463,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
} }
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
// Constructor is in eax. // Constructor is in eax.
DCHECK(lit != NULL); DCHECK(lit != NULL);
__ push(eax); __ push(eax);
...@@ -2474,10 +2475,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2474,10 +2475,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
__ mov(scratch, FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset)); __ mov(scratch, FieldOperand(eax, JSFunction::kPrototypeOrInitialMapOffset));
__ Push(scratch); __ Push(scratch);
// store_slot_index points to the vector IC slot for the next store IC used.
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (int i = 0; i < lit->properties()->length(); i++) { for (int i = 0; i < lit->properties()->length(); i++) {
ObjectLiteral::Property* property = lit->properties()->at(i); ObjectLiteral::Property* property = lit->properties()->at(i);
Expression* value = property->value(); Expression* value = property->value();
...@@ -2500,7 +2497,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2500,7 +2497,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2, EmitSetHomeObjectIfNeeded(value, 2,
lit->SlotForHomeObject(value, &store_slot_index)); lit->SlotForHomeObject(value, used_store_slots));
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
...@@ -2528,10 +2525,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2528,10 +2525,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// constructor // constructor
__ CallRuntime(Runtime::kToFastProperties, 1); __ CallRuntime(Runtime::kToFastProperties, 1);
// Verify that compilation exactly consumed the number of store ic slots that
// the ClassLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
} }
......
...@@ -2526,7 +2526,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, ...@@ -2526,7 +2526,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
} }
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
// Constructor is in v0. // Constructor is in v0.
DCHECK(lit != NULL); DCHECK(lit != NULL);
__ push(v0); __ push(v0);
...@@ -2538,10 +2539,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2538,10 +2539,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset)); FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
__ push(scratch); __ push(scratch);
// store_slot_index points to the vector IC slot for the next store IC used.
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (int i = 0; i < lit->properties()->length(); i++) { for (int i = 0; i < lit->properties()->length(); i++) {
ObjectLiteral::Property* property = lit->properties()->at(i); ObjectLiteral::Property* property = lit->properties()->at(i);
Expression* value = property->value(); Expression* value = property->value();
...@@ -2565,7 +2562,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2565,7 +2562,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2, EmitSetHomeObjectIfNeeded(value, 2,
lit->SlotForHomeObject(value, &store_slot_index)); lit->SlotForHomeObject(value, used_store_slots));
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
...@@ -2598,10 +2595,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2598,10 +2595,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// constructor // constructor
__ CallRuntime(Runtime::kToFastProperties, 1); __ CallRuntime(Runtime::kToFastProperties, 1);
// Verify that compilation exactly consumed the number of store ic slots that
// the ClassLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
} }
......
...@@ -2525,7 +2525,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, ...@@ -2525,7 +2525,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
} }
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
// Constructor is in v0. // Constructor is in v0.
DCHECK(lit != NULL); DCHECK(lit != NULL);
__ push(v0); __ push(v0);
...@@ -2537,10 +2538,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2537,10 +2538,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset)); FieldMemOperand(v0, JSFunction::kPrototypeOrInitialMapOffset));
__ push(scratch); __ push(scratch);
// store_slot_index points to the vector IC slot for the next store IC used.
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (int i = 0; i < lit->properties()->length(); i++) { for (int i = 0; i < lit->properties()->length(); i++) {
ObjectLiteral::Property* property = lit->properties()->at(i); ObjectLiteral::Property* property = lit->properties()->at(i);
Expression* value = property->value(); Expression* value = property->value();
...@@ -2564,7 +2561,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2564,7 +2561,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2, EmitSetHomeObjectIfNeeded(value, 2,
lit->SlotForHomeObject(value, &store_slot_index)); lit->SlotForHomeObject(value, used_store_slots));
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
...@@ -2597,10 +2594,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2597,10 +2594,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// constructor // constructor
__ CallRuntime(Runtime::kToFastProperties, 1); __ CallRuntime(Runtime::kToFastProperties, 1);
// Verify that compilation exactly consumed the number of store ic slots that
// the ClassLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
} }
...@@ -5089,7 +5082,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) { ...@@ -5089,7 +5082,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} }
} else { } else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN); Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG); PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0); context()->Plug(v0);
} }
......
...@@ -2458,7 +2458,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr, ...@@ -2458,7 +2458,8 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
} }
void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit,
int* used_store_slots) {
// Constructor is in rax. // Constructor is in rax.
DCHECK(lit != NULL); DCHECK(lit != NULL);
__ Push(rax); __ Push(rax);
...@@ -2469,10 +2470,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2469,10 +2470,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
__ movp(scratch, FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset)); __ movp(scratch, FieldOperand(rax, JSFunction::kPrototypeOrInitialMapOffset));
__ Push(scratch); __ Push(scratch);
// store_slot_index points to the vector IC slot for the next store IC used.
// ClassLiteral::ComputeFeedbackRequirements controls the allocation of slots
// and must be updated if the number of store ICs emitted here changes.
int store_slot_index = 0;
for (int i = 0; i < lit->properties()->length(); i++) { for (int i = 0; i < lit->properties()->length(); i++) {
ObjectLiteral::Property* property = lit->properties()->at(i); ObjectLiteral::Property* property = lit->properties()->at(i);
Expression* value = property->value(); Expression* value = property->value();
...@@ -2495,7 +2492,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2495,7 +2492,7 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
VisitForStackValue(value); VisitForStackValue(value);
EmitSetHomeObjectIfNeeded(value, 2, EmitSetHomeObjectIfNeeded(value, 2,
lit->SlotForHomeObject(value, &store_slot_index)); lit->SlotForHomeObject(value, used_store_slots));
switch (property->kind()) { switch (property->kind()) {
case ObjectLiteral::Property::CONSTANT: case ObjectLiteral::Property::CONSTANT:
...@@ -2526,10 +2523,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) { ...@@ -2526,10 +2523,6 @@ void FullCodeGenerator::EmitClassDefineProperties(ClassLiteral* lit) {
// constructor // constructor
__ CallRuntime(Runtime::kToFastProperties, 1); __ CallRuntime(Runtime::kToFastProperties, 1);
// Verify that compilation exactly consumed the number of store ic slots that
// the ClassLiteral node had to offer.
DCHECK(!FLAG_vector_stores || store_slot_index == lit->slot_count());
} }
......
...@@ -201,7 +201,6 @@ const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = { ...@@ -201,7 +201,6 @@ const SharedOperatorWithLanguageMode kSharedOperatorsWithLanguageMode[] = {
SHARED(Multiply, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), SHARED(Multiply, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Divide, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), SHARED(Divide, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(Modulus, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2), SHARED(Modulus, Operator::kNoProperties, 2, 2, 1, 1, 1, 1, 2),
SHARED(StoreProperty, Operator::kNoProperties, 3, 2, 1, 1, 0, 1, 2),
#undef SHARED #undef SHARED
}; };
......
...@@ -739,8 +739,10 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) { ...@@ -739,8 +739,10 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArray) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* effect = graph()->start(); Node* effect = graph()->start();
Node* control = graph()->start(); Node* control = graph()->start();
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode), ResolvedFeedbackSlot slot;
base, key, value, context); Node* node =
graph()->NewNode(javascript()->StoreProperty(language_mode, slot),
base, key, value, context);
for (int i = 0; for (int i = 0;
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) { i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
node->AppendInput(zone(), EmptyFrameState()); node->AppendInput(zone(), EmptyFrameState());
...@@ -785,8 +787,10 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) { ...@@ -785,8 +787,10 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithConversion) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* effect = graph()->start(); Node* effect = graph()->start();
Node* control = graph()->start(); Node* control = graph()->start();
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode), ResolvedFeedbackSlot slot;
base, key, value, context); Node* node =
graph()->NewNode(javascript()->StoreProperty(language_mode, slot),
base, key, value, context);
for (int i = 0; for (int i = 0;
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) { i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
node->AppendInput(zone(), EmptyFrameState()); node->AppendInput(zone(), EmptyFrameState());
...@@ -844,8 +848,10 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) { ...@@ -844,8 +848,10 @@ TEST_F(JSTypedLoweringTest, JSStorePropertyToExternalTypedArrayWithSafeKey) {
Node* context = UndefinedConstant(); Node* context = UndefinedConstant();
Node* effect = graph()->start(); Node* effect = graph()->start();
Node* control = graph()->start(); Node* control = graph()->start();
Node* node = graph()->NewNode(javascript()->StoreProperty(language_mode), ResolvedFeedbackSlot slot;
base, key, value, context); Node* node =
graph()->NewNode(javascript()->StoreProperty(language_mode, slot),
base, key, value, context);
for (int i = 0; for (int i = 0;
i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) { i < OperatorProperties::GetFrameStateInputCount(node->op()); i++) {
node->AppendInput(zone(), EmptyFrameState()); node->AppendInput(zone(), EmptyFrameState());
......
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