[ast] Remove BailoutId and TypeFeedbackId from AST.

This removes both {BailoutId} as well as {TypeFeedbackId} numbers from
almost all AST nodes. The only exception are {IterationStatement} nodes
which still require an ID for on-stack replacement support.

R=verwaest@chromium.org
BUG=v8:6409

Change-Id: I5f7b7673ae5797b9cbc9741144d304f0d31d4446
Reviewed-on: https://chromium-review.googlesource.com/538792
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45991}
This commit is contained in:
Michael Starzinger 2017-06-16 15:15:14 +02:00 committed by Commit Bot
parent f626d5df7e
commit bc717ae84b
22 changed files with 151 additions and 1613 deletions

View File

@ -1513,8 +1513,6 @@ v8_source_set("v8_base") {
"src/crankshaft/lithium-inl.h",
"src/crankshaft/lithium.cc",
"src/crankshaft/lithium.h",
"src/crankshaft/typing.cc",
"src/crankshaft/typing.h",
"src/crankshaft/unique.h",
"src/date.cc",
"src/date.h",

View File

@ -148,14 +148,12 @@ void AstNumberingVisitor::VisitNativeFunctionLiteral(
NativeFunctionLiteral* node) {
IncrementNodeCount();
DisableOptimization(kNativeFunctionLiteral);
node->set_base_id(ReserveIdRange(NativeFunctionLiteral::num_ids()));
ReserveFeedbackSlots(node);
}
void AstNumberingVisitor::VisitDoExpression(DoExpression* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(DoExpression::num_ids()));
Visit(node->block());
Visit(node->result());
}
@ -163,13 +161,11 @@ void AstNumberingVisitor::VisitDoExpression(DoExpression* node) {
void AstNumberingVisitor::VisitLiteral(Literal* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(Literal::num_ids()));
}
void AstNumberingVisitor::VisitRegExpLiteral(RegExpLiteral* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(RegExpLiteral::num_ids()));
ReserveFeedbackSlots(node);
}
@ -187,7 +183,6 @@ void AstNumberingVisitor::VisitVariableProxyReference(VariableProxy* node) {
default:
break;
}
node->set_base_id(ReserveIdRange(VariableProxy::num_ids()));
}
void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node,
@ -203,7 +198,6 @@ void AstNumberingVisitor::VisitVariableProxy(VariableProxy* node) {
void AstNumberingVisitor::VisitThisFunction(ThisFunction* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(ThisFunction::num_ids()));
}
@ -211,7 +205,6 @@ void AstNumberingVisitor::VisitSuperPropertyReference(
SuperPropertyReference* node) {
IncrementNodeCount();
DisableFullCodegenAndCrankshaft(kSuperReference);
node->set_base_id(ReserveIdRange(SuperPropertyReference::num_ids()));
Visit(node->this_var());
Visit(node->home_object());
}
@ -220,7 +213,6 @@ void AstNumberingVisitor::VisitSuperPropertyReference(
void AstNumberingVisitor::VisitSuperCallReference(SuperCallReference* node) {
IncrementNodeCount();
DisableFullCodegenAndCrankshaft(kSuperReference);
node->set_base_id(ReserveIdRange(SuperCallReference::num_ids()));
Visit(node->this_var());
Visit(node->new_target_var());
Visit(node->this_function_var());
@ -245,21 +237,18 @@ void AstNumberingVisitor::VisitSuspend(Suspend* node) {
node->set_suspend_id(suspend_count_);
suspend_count_++;
IncrementNodeCount();
node->set_base_id(ReserveIdRange(Suspend::num_ids()));
Visit(node->expression());
}
void AstNumberingVisitor::VisitThrow(Throw* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(Throw::num_ids()));
Visit(node->exception());
}
void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(UnaryOperation::num_ids()));
if ((node->op() == Token::TYPEOF) && node->expression()->IsVariableProxy()) {
VariableProxy* proxy = node->expression()->AsVariableProxy();
VisitVariableProxy(proxy, INSIDE_TYPEOF);
@ -271,7 +260,6 @@ void AstNumberingVisitor::VisitUnaryOperation(UnaryOperation* node) {
void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(CountOperation::num_ids()));
Visit(node->expression());
ReserveFeedbackSlots(node);
}
@ -279,7 +267,6 @@ void AstNumberingVisitor::VisitCountOperation(CountOperation* node) {
void AstNumberingVisitor::VisitBlock(Block* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(Block::num_ids()));
Scope* scope = node->scope();
if (scope != nullptr) {
LanguageModeScope language_mode_scope(this, scope->language_mode());
@ -305,7 +292,6 @@ void AstNumberingVisitor::VisitFunctionDeclaration(FunctionDeclaration* node) {
void AstNumberingVisitor::VisitCallRuntime(CallRuntime* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(CallRuntime::num_ids()));
VisitArguments(node->arguments());
// To support catch prediction within async/await:
//
@ -401,7 +387,6 @@ void AstNumberingVisitor::VisitTryFinallyStatement(TryFinallyStatement* node) {
void AstNumberingVisitor::VisitPropertyReference(Property* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(Property::num_ids()));
Visit(node->key());
Visit(node->obj());
}
@ -425,7 +410,6 @@ void AstNumberingVisitor::VisitProperty(Property* node) {
void AstNumberingVisitor::VisitAssignment(Assignment* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(Assignment::num_ids()));
if (node->is_compound()) VisitBinaryOperation(node->binary_operation());
VisitReference(node->target());
@ -436,7 +420,6 @@ void AstNumberingVisitor::VisitAssignment(Assignment* node) {
void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(BinaryOperation::num_ids()));
Visit(node->left());
Visit(node->right());
ReserveFeedbackSlots(node);
@ -445,7 +428,6 @@ void AstNumberingVisitor::VisitBinaryOperation(BinaryOperation* node) {
void AstNumberingVisitor::VisitCompareOperation(CompareOperation* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(CompareOperation::num_ids()));
Visit(node->left());
Visit(node->right());
ReserveFeedbackSlots(node);
@ -455,7 +437,6 @@ void AstNumberingVisitor::VisitSpread(Spread* node) {
IncrementNodeCount();
// We can only get here from spread calls currently.
DisableFullCodegenAndCrankshaft(kSpreadCall);
node->set_base_id(ReserveIdRange(Spread::num_ids()));
Visit(node->expression());
}
@ -466,7 +447,6 @@ void AstNumberingVisitor::VisitEmptyParentheses(EmptyParentheses* node) {
void AstNumberingVisitor::VisitGetIterator(GetIterator* node) {
IncrementNodeCount();
DisableFullCodegenAndCrankshaft(kGetIterator);
node->set_base_id(ReserveIdRange(GetIterator::num_ids()));
Visit(node->iterable());
ReserveFeedbackSlots(node);
}
@ -507,7 +487,6 @@ void AstNumberingVisitor::VisitForOfStatement(ForOfStatement* node) {
void AstNumberingVisitor::VisitConditional(Conditional* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(Conditional::num_ids()));
Visit(node->condition());
Visit(node->then_expression());
Visit(node->else_expression());
@ -516,7 +495,6 @@ void AstNumberingVisitor::VisitConditional(Conditional* node) {
void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(IfStatement::num_ids()));
Visit(node->condition());
Visit(node->then_statement());
if (node->HasElseStatement()) {
@ -527,7 +505,6 @@ void AstNumberingVisitor::VisitIfStatement(IfStatement* node) {
void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(SwitchStatement::num_ids()));
Visit(node->tag());
ZoneList<CaseClause*>* cases = node->cases();
for (int i = 0; i < cases->length(); i++) {
@ -538,7 +515,6 @@ void AstNumberingVisitor::VisitSwitchStatement(SwitchStatement* node) {
void AstNumberingVisitor::VisitCaseClause(CaseClause* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(CaseClause::num_ids()));
if (!node->is_default()) Visit(node->label());
VisitStatements(node->statements());
ReserveFeedbackSlots(node);
@ -561,7 +537,6 @@ void AstNumberingVisitor::VisitForStatement(ForStatement* node) {
void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
IncrementNodeCount();
DisableFullCodegenAndCrankshaft(kClassLiteral);
node->set_base_id(ReserveIdRange(ClassLiteral::num_ids()));
LanguageModeScope language_mode_scope(this, STRICT);
if (node->extends()) Visit(node->extends());
if (node->constructor()) Visit(node->constructor());
@ -577,7 +552,6 @@ void AstNumberingVisitor::VisitClassLiteral(ClassLiteral* node) {
void AstNumberingVisitor::VisitObjectLiteral(ObjectLiteral* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(node->num_ids()));
for (int i = 0; i < node->properties()->length(); i++) {
VisitLiteralProperty(node->properties()->at(i));
}
@ -598,7 +572,6 @@ void AstNumberingVisitor::VisitLiteralProperty(LiteralProperty* node) {
void AstNumberingVisitor::VisitArrayLiteral(ArrayLiteral* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(node->num_ids()));
for (int i = 0; i < node->values()->length(); i++) {
Visit(node->values()->at(i));
}
@ -613,7 +586,6 @@ void AstNumberingVisitor::VisitCall(Call* node) {
}
IncrementNodeCount();
ReserveFeedbackSlots(node);
node->set_base_id(ReserveIdRange(Call::num_ids()));
Visit(node->expression());
VisitArguments(node->arguments());
}
@ -622,7 +594,6 @@ void AstNumberingVisitor::VisitCall(Call* node) {
void AstNumberingVisitor::VisitCallNew(CallNew* node) {
IncrementNodeCount();
ReserveFeedbackSlots(node);
node->set_base_id(ReserveIdRange(CallNew::num_ids()));
Visit(node->expression());
VisitArguments(node->arguments());
}
@ -650,7 +621,6 @@ void AstNumberingVisitor::VisitArguments(ZoneList<Expression*>* arguments) {
void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(FunctionLiteral::num_ids()));
if (node->ShouldEagerCompile()) {
if (eager_literals_) {
eager_literals_->Add(new (zone())
@ -671,7 +641,6 @@ void AstNumberingVisitor::VisitFunctionLiteral(FunctionLiteral* node) {
void AstNumberingVisitor::VisitRewritableExpression(
RewritableExpression* node) {
IncrementNodeCount();
node->set_base_id(ReserveIdRange(RewritableExpression::num_ids()));
Visit(node->expression());
}

View File

@ -851,26 +851,6 @@ void MaterializedLiteral::BuildConstants(Isolate* isolate) {
DCHECK(IsRegExpLiteral());
}
void UnaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
// TODO(olivf) If this Operation is used in a test context, then the
// expression has a ToBoolean stub and we want to collect the type
// information. However the GraphBuilder expects it to be on the instruction
// corresponding to the TestContext, therefore we have to store it here and
// not on the operand.
set_to_boolean_types(oracle->ToBooleanTypes(expression()->test_id()));
}
void BinaryOperation::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
// TODO(olivf) If this Operation is used in a test context, then the right
// hand side has a ToBoolean stub and we want to collect the type information.
// However the GraphBuilder expects it to be on the instruction corresponding
// to the TestContext, therefore we have to store it here and not on the
// right hand operand.
set_to_boolean_types(oracle->ToBooleanTypes(right()->test_id()));
}
void BinaryOperation::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,
FeedbackSlotCache* cache) {
@ -1004,19 +984,6 @@ bool CompareOperation::IsLiteralCompareNull(Expression** expr) {
// ----------------------------------------------------------------------------
// Recording of type feedback
// TODO(rossberg): all RecordTypeFeedback functions should disappear
// once we use the common type field in the AST consistently.
void Expression::RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle) {
if (IsUnaryOperation()) {
AsUnaryOperation()->RecordToBooleanTypeFeedback(oracle);
} else if (IsBinaryOperation()) {
AsBinaryOperation()->RecordToBooleanTypeFeedback(oracle);
} else {
set_to_boolean_types(oracle->ToBooleanTypes(test_id()));
}
}
void SmallMapList::AddMapIfMissing(Handle<Map> map, Zone* zone) {
if (!Map::TryUpdate(map).ToHandle(&map)) return;
for (int i = 0; i < length(); ++i) {
@ -1123,10 +1090,7 @@ Call::CallType Call::GetCallType() const {
CaseClause::CaseClause(Expression* label, ZoneList<Statement*>* statements,
int pos)
: Expression(pos, kCaseClause),
label_(label),
statements_(statements),
compare_type_(AstType::None()) {}
: Expression(pos, kCaseClause), label_(label), statements_(statements) {}
void CaseClause::AssignFeedbackSlots(FeedbackVectorSpec* spec,
LanguageMode language_mode,

View File

@ -122,7 +122,6 @@ class Expression;
class IterationStatement;
class MaterializedLiteral;
class Statement;
class TypeFeedbackOracle;
#define DEF_FORWARD_DECLARATION(type) class type;
AST_NODE_LIST(DEF_FORWARD_DECLARATION)
@ -330,45 +329,15 @@ class Expression : public AstNode {
// True iff the expression is a valid target for an assignment.
bool IsValidReferenceExpressionOrThis() const;
// TODO(rossberg): this should move to its own AST node eventually.
void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
uint16_t to_boolean_types() const {
return ToBooleanTypesField::decode(bit_field_);
}
SmallMapList* GetReceiverTypes();
KeyedAccessStoreMode GetStoreMode() const;
IcCheckType GetKeyType() const;
bool IsMonomorphic() const;
void set_base_id(int id) { base_id_ = id; }
static int num_ids() { return parent_num_ids() + 2; }
BailoutId id() const { return BailoutId(local_id(0)); }
TypeFeedbackId test_id() const { return TypeFeedbackId(local_id(1)); }
private:
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
int base_id_;
class ToBooleanTypesField
: public BitField<uint16_t, AstNode::kNextBitFieldIndex, 9> {};
protected:
Expression(int pos, NodeType type)
: AstNode(pos, type), base_id_(BailoutId::None().ToInt()) {
bit_field_ = ToBooleanTypesField::update(bit_field_, 0);
}
Expression(int pos, NodeType type) : AstNode(pos, type) {}
static int parent_num_ids() { return 0; }
void set_to_boolean_types(uint16_t types) {
bit_field_ = ToBooleanTypesField::update(bit_field_, types);
}
int base_id() const {
DCHECK(!BailoutId(base_id_).IsNone());
return base_id_;
}
static const uint8_t kNextBitFieldIndex = ToBooleanTypesField::kNext;
static const uint8_t kNextBitFieldIndex = AstNode::kNextBitFieldIndex;
};
@ -391,19 +360,11 @@ class BreakableStatement : public Statement {
return BreakableTypeField::decode(bit_field_) == TARGET_FOR_ANONYMOUS;
}
void set_base_id(int id) { base_id_ = id; }
static int num_ids() { return parent_num_ids() + 2; }
BailoutId EntryId() const { return BailoutId(local_id(0)); }
BailoutId ExitId() const { return BailoutId(local_id(1)); }
private:
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
BreakableType breakableType() const {
return BreakableTypeField::decode(bit_field_);
}
int base_id_;
Label break_target_;
ZoneList<const AstRawString*>* labels_;
@ -414,18 +375,12 @@ class BreakableStatement : public Statement {
BreakableStatement(ZoneList<const AstRawString*>* labels,
BreakableType breakable_type, int position, NodeType type)
: Statement(position, type),
base_id_(BailoutId::None().ToInt()),
labels_(labels) {
DCHECK(labels == NULL || labels->length() > 0);
bit_field_ |= BreakableTypeField::encode(breakable_type);
}
static int parent_num_ids() { return 0; }
int base_id() const {
DCHECK(!BailoutId(base_id_).IsNone());
return base_id_;
}
static const uint8_t kNextBitFieldIndex = BreakableTypeField::kNext;
};
@ -437,9 +392,6 @@ class Block final : public BreakableStatement {
return IgnoreCompletionField::decode(bit_field_);
}
static int num_ids() { return parent_num_ids() + 1; }
BailoutId DeclsId() const { return BailoutId(local_id(0)); }
bool IsJump() const {
return !statements_.is_empty() && statements_.last()->IsJump()
&& labels() == NULL; // Good enough as an approximation...
@ -458,8 +410,6 @@ class Block final : public BreakableStatement {
scope_(NULL) {
bit_field_ |= IgnoreCompletionField::encode(ignore_completion_value);
}
static int parent_num_ids() { return BreakableStatement::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
ZoneList<Statement*> statements_;
Scope* scope_;
@ -484,8 +434,6 @@ class DoExpression final : public Expression {
DCHECK_NOT_NULL(block_);
DCHECK_NOT_NULL(result_);
}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Block* block_;
VariableProxy* result_;
@ -555,6 +503,7 @@ class IterationStatement : public BreakableStatement {
first_suspend_id_ = first_suspend_id;
}
void set_base_id(int id) { base_id_ = id; }
static int num_ids() { return parent_num_ids() + 1; }
BailoutId OsrEntryId() const { return BailoutId(local_id(0)); }
@ -565,10 +514,11 @@ class IterationStatement : public BreakableStatement {
IterationStatement(ZoneList<const AstRawString*>* labels, int pos,
NodeType type)
: BreakableStatement(labels, TARGET_FOR_ANONYMOUS, pos, type),
base_id_(BailoutId::None().ToInt()),
body_(NULL),
suspend_count_(0),
first_suspend_id_(0) {}
static int parent_num_ids() { return BreakableStatement::num_ids(); }
static int parent_num_ids() { return 0; }
void Initialize(Statement* body, const SourceRange& body_range = {}) {
body_ = body;
body_range_ = body_range;
@ -579,7 +529,12 @@ class IterationStatement : public BreakableStatement {
private:
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
int base_id() const {
DCHECK(!BailoutId(base_id_).IsNone());
return base_id_;
}
int base_id_;
Statement* body_;
SourceRange body_range_;
Label continue_target_;
@ -599,18 +554,11 @@ class DoWhileStatement final : public IterationStatement {
Expression* cond() const { return cond_; }
void set_cond(Expression* e) { cond_ = e; }
static int num_ids() { return parent_num_ids() + 2; }
BailoutId ContinueId() const { return BailoutId(local_id(0)); }
BailoutId StackCheckId() const { return BackEdgeId(); }
BailoutId BackEdgeId() const { return BailoutId(local_id(1)); }
private:
friend class AstNodeFactory;
DoWhileStatement(ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(labels, pos, kDoWhileStatement), cond_(NULL) {}
static int parent_num_ids() { return IterationStatement::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Expression* cond_;
};
@ -627,18 +575,11 @@ class WhileStatement final : public IterationStatement {
Expression* cond() const { return cond_; }
void set_cond(Expression* e) { cond_ = e; }
static int num_ids() { return parent_num_ids() + 1; }
BailoutId ContinueId() const { return EntryId(); }
BailoutId StackCheckId() const { return BodyId(); }
BailoutId BodyId() const { return BailoutId(local_id(0)); }
private:
friend class AstNodeFactory;
WhileStatement(ZoneList<const AstRawString*>* labels, int pos)
: IterationStatement(labels, pos, kWhileStatement), cond_(NULL) {}
static int parent_num_ids() { return IterationStatement::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Expression* cond_;
};
@ -662,11 +603,6 @@ class ForStatement final : public IterationStatement {
void set_cond(Expression* e) { cond_ = e; }
void set_next(Statement* s) { next_ = s; }
static int num_ids() { return parent_num_ids() + 2; }
BailoutId ContinueId() const { return BailoutId(local_id(0)); }
BailoutId StackCheckId() const { return BodyId(); }
BailoutId BodyId() const { return BailoutId(local_id(1)); }
private:
friend class AstNodeFactory;
@ -675,8 +611,6 @@ class ForStatement final : public IterationStatement {
init_(NULL),
cond_(NULL),
next_(NULL) {}
static int parent_num_ids() { return IterationStatement::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Statement* init_;
Expression* cond_;
@ -737,16 +671,6 @@ class ForInStatement final : public ForEachStatement {
bit_field_ = ForInTypeField::update(bit_field_, type);
}
static int num_ids() { return parent_num_ids() + 7; }
BailoutId BodyId() const { return BailoutId(local_id(0)); }
BailoutId EnumId() const { return BailoutId(local_id(1)); }
BailoutId ToObjectId() const { return BailoutId(local_id(2)); }
BailoutId PrepareId() const { return BailoutId(local_id(3)); }
BailoutId FilterId() const { return BailoutId(local_id(4)); }
BailoutId AssignmentId() const { return BailoutId(local_id(5)); }
BailoutId IncrementId() const { return BailoutId(local_id(6)); }
BailoutId StackCheckId() const { return BodyId(); }
private:
friend class AstNodeFactory;
@ -757,9 +681,6 @@ class ForInStatement final : public ForEachStatement {
bit_field_ = ForInTypeField::update(bit_field_, SLOW_FOR_IN);
}
static int parent_num_ids() { return ForEachStatement::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Expression* each_;
Expression* subject_;
FeedbackSlot each_slot_;
@ -943,16 +864,6 @@ class CaseClause final : public Expression {
Label* body_target() { return &body_target_; }
ZoneList<Statement*>* statements() const { return statements_; }
static int num_ids() { return parent_num_ids() + 2; }
BailoutId EntryId() const { return BailoutId(local_id(0)); }
TypeFeedbackId CompareId() { return TypeFeedbackId(local_id(1)); }
AstType* compare_type() { return compare_type_; }
void set_compare_type(AstType* type) { compare_type_ = type; }
// CaseClause will have both a slot in the feedback vector and the
// TypeFeedbackId to record the type information. TypeFeedbackId is used by
// full codegen and the feedback vector slot is used by interpreter.
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
FeedbackSlotCache* cache);
@ -961,15 +872,12 @@ class CaseClause final : public Expression {
private:
friend class AstNodeFactory;
static int parent_num_ids() { return Expression::num_ids(); }
CaseClause(Expression* label, ZoneList<Statement*>* statements, int pos);
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
FeedbackSlot feedback_slot_;
Expression* label_;
Label body_target_;
ZoneList<Statement*>* statements_;
AstType* compare_type_;
};
@ -1024,12 +932,6 @@ class IfStatement final : public Statement {
&& HasElseStatement() && else_statement()->IsJump();
}
void set_base_id(int id) { base_id_ = id; }
static int num_ids() { return parent_num_ids() + 3; }
BailoutId IfId() const { return BailoutId(local_id(0)); }
BailoutId ThenId() const { return BailoutId(local_id(1)); }
BailoutId ElseId() const { return BailoutId(local_id(2)); }
private:
friend class AstNodeFactory;
@ -1037,21 +939,12 @@ class IfStatement final : public Statement {
Statement* else_statement, int pos, SourceRange then_range,
SourceRange else_range)
: Statement(pos, kIfStatement),
base_id_(BailoutId::None().ToInt()),
condition_(condition),
then_statement_(then_statement),
else_statement_(else_statement),
then_range_(then_range),
else_range_(else_range) {}
static int parent_num_ids() { return 0; }
int base_id() const {
DCHECK(!BailoutId(base_id_).IsNone());
return base_id_;
}
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
int base_id_;
Expression* condition_;
Statement* then_statement_;
Statement* else_statement_;
@ -1214,20 +1107,12 @@ class Literal final : public Expression {
uint32_t Hash();
static bool Match(void* literal1, void* literal2);
static int num_ids() { return parent_num_ids() + 1; }
TypeFeedbackId LiteralFeedbackId() const {
return TypeFeedbackId(local_id(0));
}
private:
friend class AstNodeFactory;
Literal(const AstValue* value, int position)
: Expression(position, kLiteral), value_(value) {}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
const AstValue* value_;
};
@ -1445,21 +1330,11 @@ class ObjectLiteral final : public MaterializedLiteral {
};
struct Accessors: public ZoneObject {
Accessors() : getter(NULL), setter(NULL), bailout_id(BailoutId::None()) {}
Accessors() : getter(NULL), setter(NULL) {}
ObjectLiteralProperty* getter;
ObjectLiteralProperty* setter;
BailoutId bailout_id;
};
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
// Return an AST id for a property that is used in simulate instructions.
BailoutId GetIdForPropertySet(int i) { return BailoutId(local_id(i + 1)); }
// Unlike other AST nodes, this number of bailout IDs allocated for an
// ObjectLiteral can vary, so num_ids() is not a static method.
int num_ids() const { return parent_num_ids() + 1 + properties()->length(); }
// Object literals need one feedback slot for each non-trivial value, as well
// as some slots for home objects.
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
@ -1480,9 +1355,6 @@ class ObjectLiteral final : public MaterializedLiteral {
HasNullPrototypeField::encode(false);
}
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
void InitFlagsForPendingNullPrototype(int i);
void set_fast_elements(bool fast_elements) {
@ -1565,15 +1437,6 @@ class ArrayLiteral final : public MaterializedLiteral {
ZoneList<Expression*>* values() const { return values_; }
BailoutId CreateLiteralId() const { return BailoutId(local_id(0)); }
// Return an AST id for an element that is used in simulate instructions.
BailoutId GetIdForElement(int i) { return BailoutId(local_id(i + 1)); }
// Unlike other AST nodes, this number of bailout IDs allocated for an
// ArrayLiteral can vary, so num_ids() is not a static method.
int num_ids() const { return parent_num_ids() + 1 + values()->length(); }
// Populate the depth field and flags.
void InitDepthAndFlags();
@ -1626,9 +1489,6 @@ class ArrayLiteral final : public MaterializedLiteral {
first_spread_index_(first_spread_index),
values_(values) {}
static int parent_num_ids() { return MaterializedLiteral::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
int first_spread_index_;
FeedbackSlot literal_slot_;
Handle<ConstantElementsPair> constant_elements_;
@ -1701,8 +1561,6 @@ class VariableProxy final : public Expression {
FeedbackSlot VariableFeedbackSlot() { return variable_feedback_slot_; }
static int num_ids() { return parent_num_ids() + 1; }
BailoutId BeforeId() const { return BailoutId(local_id(0)); }
void set_next_unresolved(VariableProxy* next) { next_unresolved_ = next; }
VariableProxy* next_unresolved() { return next_unresolved_; }
@ -1714,9 +1572,6 @@ class VariableProxy final : public Expression {
int start_position);
explicit VariableProxy(const VariableProxy* copy_from);
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
class IsThisField : public BitField<bool, Expression::kNextBitFieldIndex, 1> {
};
class IsAssignedField : public BitField<bool, IsThisField::kNext, 1> {};
@ -1755,9 +1610,6 @@ class Property final : public Expression {
void set_obj(Expression* e) { obj_ = e; }
void set_key(Expression* e) { key_ = e; }
static int num_ids() { return parent_num_ids() + 1; }
BailoutId LoadId() const { return BailoutId(local_id(0)); }
bool IsStringAccess() const {
return IsStringAccessField::decode(bit_field_);
}
@ -1822,9 +1674,6 @@ class Property final : public Expression {
InlineCacheStateField::encode(UNINITIALIZED);
}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
class IsForCallField
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
class IsStringAccessField : public BitField<bool, IsForCallField::kNext, 1> {
@ -1881,10 +1730,6 @@ class Call final : public Expression {
allocation_site_ = site;
}
static int num_ids() { return parent_num_ids() + 2; }
BailoutId ReturnId() const { return BailoutId(local_id(0)); }
BailoutId CallId() const { return BailoutId(local_id(1)); }
bool is_uninitialized() const {
return IsUninitializedField::decode(bit_field_);
}
@ -1942,9 +1787,6 @@ class Call final : public Expression {
}
}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
class IsUninitializedField
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
class IsTailField : public BitField<bool, IsUninitializedField::kNext, 1> {};
@ -1984,10 +1826,6 @@ class CallNew final : public Expression {
return allocation_site_;
}
static int num_ids() { return parent_num_ids() + 1; }
static int feedback_slots() { return 1; }
BailoutId ReturnId() const { return BailoutId(local_id(0)); }
void set_allocation_site(Handle<AllocationSite> site) {
allocation_site_ = site;
}
@ -2014,9 +1852,6 @@ class CallNew final : public Expression {
bit_field_ |= IsMonomorphicField::encode(false);
}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
FeedbackSlot callnew_feedback_slot_;
Expression* expression_;
ZoneList<Expression*>* arguments_;
@ -2050,8 +1885,6 @@ class CallRuntime final : public Expression {
return function_;
}
static int num_ids() { return parent_num_ids() + 1; }
BailoutId CallId() { return BailoutId(local_id(0)); }
const char* debug_name();
private:
@ -2068,9 +1901,6 @@ class CallRuntime final : public Expression {
function_(NULL),
arguments_(arguments) {}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
int context_index_;
const Runtime::Function* function_;
ZoneList<Expression*>* arguments_;
@ -2083,14 +1913,6 @@ class UnaryOperation final : public Expression {
Expression* expression() const { return expression_; }
void set_expression(Expression* e) { expression_ = e; }
// For unary not (Token::NOT), the AST ids where true and false will
// actually be materialized, respectively.
static int num_ids() { return parent_num_ids() + 2; }
BailoutId MaterializeTrueId() const { return BailoutId(local_id(0)); }
BailoutId MaterializeFalseId() const { return BailoutId(local_id(1)); }
void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
private:
friend class AstNodeFactory;
@ -2100,9 +1922,6 @@ class UnaryOperation final : public Expression {
DCHECK(Token::IsUnaryOp(op));
}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Expression* expression_;
class OperatorField
@ -2133,23 +1952,11 @@ class BinaryOperation final : public Expression {
}
}
// The short-circuit logical operations need an AST ID for their
// right-hand subexpression.
static int num_ids() { return parent_num_ids() + 2; }
BailoutId RightId() const { return BailoutId(local_id(0)); }
// BinaryOperation will have both a slot in the feedback vector and the
// TypeFeedbackId to record the type information. TypeFeedbackId is used
// by full codegen and the feedback vector slot is used by interpreter.
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
FeedbackSlotCache* cache);
FeedbackSlot BinaryOperationFeedbackSlot() const { return feedback_slot_; }
TypeFeedbackId BinaryOperationFeedbackId() const {
return TypeFeedbackId(local_id(1));
}
// Returns true if one side is a Smi literal, returning the other side's
// sub-expression in |subexpr| and the literal Smi in |literal|.
bool IsSmiLiteralOperation(Expression** subexpr, Smi** literal);
@ -2162,8 +1969,6 @@ class BinaryOperation final : public Expression {
if (arg.IsJust()) fixed_right_arg_value_ = arg.FromJust();
}
void RecordToBooleanTypeFeedback(TypeFeedbackOracle* oracle);
private:
friend class AstNodeFactory;
@ -2177,9 +1982,6 @@ class BinaryOperation final : public Expression {
DCHECK(Token::IsBinaryOp(op));
}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
FeedbackSlot feedback_slot_;
Expression* left_;
Expression* right_;
@ -2213,24 +2015,12 @@ class CountOperation final : public Expression {
KeyedAccessStoreMode GetStoreMode() const {
return StoreModeField::decode(bit_field_);
}
AstType* type() const { return type_; }
void set_key_type(IcCheckType type) {
bit_field_ = KeyTypeField::update(bit_field_, type);
}
void set_store_mode(KeyedAccessStoreMode mode) {
bit_field_ = StoreModeField::update(bit_field_, mode);
}
void set_type(AstType* type) { type_ = type; }
static int num_ids() { return parent_num_ids() + 4; }
BailoutId AssignmentId() const { return BailoutId(local_id(0)); }
BailoutId ToNumberId() const { return BailoutId(local_id(1)); }
TypeFeedbackId CountBinOpFeedbackId() const {
return TypeFeedbackId(local_id(2));
}
TypeFeedbackId CountStoreFeedbackId() const {
return TypeFeedbackId(local_id(3));
}
// Feedback slot for binary operation is only used by ignition.
FeedbackSlot CountBinaryOpFeedbackSlot() const {
@ -2245,15 +2035,12 @@ class CountOperation final : public Expression {
friend class AstNodeFactory;
CountOperation(Token::Value op, bool is_prefix, Expression* expr, int pos)
: Expression(pos, kCountOperation), type_(NULL), expression_(expr) {
: Expression(pos, kCountOperation), expression_(expr) {
bit_field_ |=
IsPrefixField::encode(is_prefix) | KeyTypeField::encode(ELEMENT) |
StoreModeField::encode(STANDARD_STORE) | TokenField::encode(op);
}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
class IsPrefixField
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
class KeyTypeField : public BitField<IcCheckType, IsPrefixField::kNext, 1> {};
@ -2263,7 +2050,6 @@ class CountOperation final : public Expression {
FeedbackSlot slot_;
FeedbackSlot binary_operation_slot_;
AstType* type_;
Expression* expression_;
SmallMapList receiver_types_;
};
@ -2278,17 +2064,6 @@ class CompareOperation final : public Expression {
void set_left(Expression* e) { left_ = e; }
void set_right(Expression* e) { right_ = e; }
// Type feedback information.
static int num_ids() { return parent_num_ids() + 1; }
TypeFeedbackId CompareOperationFeedbackId() const {
return TypeFeedbackId(local_id(0));
}
AstType* combined_type() const { return combined_type_; }
void set_combined_type(AstType* type) { combined_type_ = type; }
// CompareOperation will have both a slot in the feedback vector and the
// TypeFeedbackId to record the type information. TypeFeedbackId is used
// by full codegen and the feedback vector slot is used by interpreter.
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
FeedbackSlotCache* cache);
@ -2304,21 +2079,14 @@ class CompareOperation final : public Expression {
CompareOperation(Token::Value op, Expression* left, Expression* right,
int pos)
: Expression(pos, kCompareOperation),
left_(left),
right_(right),
combined_type_(AstType::None()) {
: Expression(pos, kCompareOperation), left_(left), right_(right) {
bit_field_ |= OperatorField::encode(op);
DCHECK(Token::IsCompareOp(op));
}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
FeedbackSlot feedback_slot_;
Expression* left_;
Expression* right_;
AstType* combined_type_;
class OperatorField
: public BitField<Token::Value, Expression::kNextBitFieldIndex, 7> {};
@ -2332,8 +2100,6 @@ class Spread final : public Expression {
int expression_position() const { return expr_pos_; }
static int num_ids() { return parent_num_ids(); }
private:
friend class AstNodeFactory;
@ -2342,9 +2108,6 @@ class Spread final : public Expression {
expr_pos_(expr_pos),
expression_(expression) {}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
int expr_pos_;
Expression* expression_;
};
@ -2365,10 +2128,6 @@ class Conditional final : public Expression {
else_expression_->MarkTail();
}
static int num_ids() { return parent_num_ids() + 2; }
BailoutId ThenId() const { return BailoutId(local_id(0)); }
BailoutId ElseId() const { return BailoutId(local_id(1)); }
private:
friend class AstNodeFactory;
@ -2379,9 +2138,6 @@ class Conditional final : public Expression {
then_expression_(then_expression),
else_expression_(else_expression) {}
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Expression* condition_;
Expression* then_expression_;
Expression* else_expression_;
@ -2406,11 +2162,7 @@ class Assignment final : public Expression {
// This check relies on the definition order of token in token.h.
bool is_compound() const { return op() > Token::ASSIGN; }
static int num_ids() { return parent_num_ids() + 2; }
BailoutId AssignmentId() const { return BailoutId(local_id(0)); }
// Type feedback information.
TypeFeedbackId AssignmentFeedbackId() { return TypeFeedbackId(local_id(1)); }
bool IsUninitialized() const {
return IsUninitializedField::decode(bit_field_);
}
@ -2442,9 +2194,6 @@ class Assignment final : public Expression {
Assignment(Token::Value op, Expression* target, Expression* value, int pos);
static int parent_num_ids() { return Expression::num_ids(); }
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
class IsUninitializedField
: public BitField<bool, Expression::kNextBitFieldIndex, 1> {};
class KeyTypeField
@ -2489,8 +2238,6 @@ class RewritableExpression final : public Expression {
bit_field_ = IsRewrittenField::update(bit_field_, true);
}
static int num_ids() { return parent_num_ids(); }
private:
friend class AstNodeFactory;
@ -2501,8 +2248,6 @@ class RewritableExpression final : public Expression {
DCHECK(!expression->IsRewritableExpression());
}
int local_id(int n) const { return base_id() + parent_num_ids() + n; }
Expression* expr_;
class IsRewrittenField
@ -3052,8 +2797,6 @@ class GetIterator final : public Expression {
Expression* iterable() const { return iterable_; }
void set_iterable(Expression* iterable) { iterable_ = iterable; }
static int num_ids() { return parent_num_ids(); }
void AssignFeedbackSlots(FeedbackVectorSpec* spec, LanguageMode language_mode,
FeedbackSlotCache* cache) {
iterator_property_feedback_slot_ = spec->AddLoadICSlot();

View File

@ -96,14 +96,11 @@ class AstGraphBuilder::AstValueContext final : public AstContext {
// Context to evaluate expression for a condition value (and side effects).
class AstGraphBuilder::AstTestContext final : public AstContext {
public:
AstTestContext(AstGraphBuilder* owner, TypeFeedbackId feedback_id)
: AstContext(owner, Expression::kTest), feedback_id_(feedback_id) {}
explicit AstTestContext(AstGraphBuilder* owner)
: AstContext(owner, Expression::kTest) {}
~AstTestContext() final;
void ProduceValue(Expression* expr, Node* value) final;
Node* ConsumeValue() final;
private:
TypeFeedbackId const feedback_id_;
};
@ -421,8 +418,7 @@ void AstGraphBuilder::CreateGraphBody(bool stack_check) {
// Build a stack-check before the body.
if (stack_check) {
Node* node = NewNode(javascript()->StackCheck());
PrepareFrameState(node, BailoutId::FunctionEntry());
NewNode(javascript()->StackCheck());
}
// Visit statements in the function body.
@ -433,12 +429,6 @@ void AstGraphBuilder::CreateGraphBody(bool stack_check) {
}
// Gets the bailout id just before reading a variable proxy, but only for
// unallocated variables.
static BailoutId BeforeId(VariableProxy* proxy) {
return proxy->var()->IsUnallocated() ? proxy->BeforeId() : BailoutId::None();
}
static const char* GetDebugParameterName(Zone* zone, DeclarationScope* scope,
int index) {
#if DEBUG
@ -589,13 +579,6 @@ AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
}
Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id,
OutputFrameStateCombine combine,
bool owner_has_exception) {
DCHECK(!builder()->info()->is_deoptimization_enabled());
return builder()->GetEmptyFrameState();
}
void AstGraphBuilder::Environment::PrepareForLoopExit(
Node* loop, BitVector* assigned_variables) {
if (IsMarkedAsUnreachable()) return;
@ -658,19 +641,16 @@ AstGraphBuilder::AstTestContext::~AstTestContext() {
void AstGraphBuilder::AstEffectContext::ProduceValue(Expression* expr,
Node* value) {
// The value is ignored.
owner()->PrepareEagerCheckpoint(expr->id());
}
void AstGraphBuilder::AstValueContext::ProduceValue(Expression* expr,
Node* value) {
environment()->Push(value);
owner()->PrepareEagerCheckpoint(expr->id());
}
void AstGraphBuilder::AstTestContext::ProduceValue(Expression* expr,
Node* value) {
environment()->Push(owner()->BuildToBoolean(value, feedback_id_));
owner()->PrepareEagerCheckpoint(expr->id());
environment()->Push(owner()->BuildToBoolean(value));
}
@ -777,7 +757,7 @@ void AstGraphBuilder::VisitForEffect(Expression* expr) {
void AstGraphBuilder::VisitForTest(Expression* expr) {
AstTestContext for_condition(this, expr->test_id());
AstTestContext for_condition(this);
if (!CheckStackOverflow()) {
VisitNoStackOverflowCheck(expr);
} else {
@ -1004,7 +984,7 @@ void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
LoopBuilder while_loop(this);
while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
VisitIterationBody(stmt, &while_loop, stmt->StackCheckId());
VisitIterationBody(stmt, &while_loop);
while_loop.EndBody();
VisitForTest(stmt->cond());
Node* condition = environment()->Pop();
@ -1019,7 +999,7 @@ void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
VisitForTest(stmt->cond());
Node* condition = environment()->Pop();
while_loop.BreakUnless(condition);
VisitIterationBody(stmt, &while_loop, stmt->StackCheckId());
VisitIterationBody(stmt, &while_loop);
while_loop.EndBody();
while_loop.EndLoop();
}
@ -1036,7 +1016,7 @@ void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
} else {
for_loop.BreakUnless(jsgraph()->TrueConstant());
}
VisitIterationBody(stmt, &for_loop, stmt->StackCheckId());
VisitIterationBody(stmt, &for_loop);
for_loop.EndBody();
VisitIfNotNull(stmt->next());
for_loop.EndLoop();
@ -1122,9 +1102,7 @@ void AstGraphBuilder::VisitConditional(Conditional* expr) {
void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
PrepareEagerCheckpoint(BeforeId(expr));
Node* value = BuildVariableLoad(expr->var(), expr->id(), pair,
ast_context()->GetStateCombine());
Node* value = BuildVariableLoad(expr->var(), pair);
ast_context()->ProduceValue(expr, value);
}
@ -1143,7 +1121,6 @@ void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
expr->pattern(), expr->flags(),
FeedbackVector::GetIndex(expr->literal_slot()));
Node* literal = NewNode(op, closure);
PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(expr, literal);
}
@ -1156,8 +1133,6 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
expr->GetOrBuildConstantProperties(isolate()), expr->ComputeFlags(true),
FeedbackVector::GetIndex(expr->literal_slot()), expr->properties_count());
Node* literal = NewNode(op, closure);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
// The object is expected on the operand stack during computation of the
// property values and is the value of the entire expression.
@ -1190,9 +1165,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Handle<Name> name = key->AsPropertyName();
VectorSlotPair feedback =
CreateVectorSlotPair(property->GetSlot(0));
Node* store = BuildNamedStoreOwn(literal, name, value, feedback);
PrepareFrameState(store, key->id(),
OutputFrameStateCombine::Ignore());
BuildNamedStoreOwn(literal, name, value, feedback);
BuildSetHomeObject(value, literal, property, 1);
} else {
VisitForEffect(property->value());
@ -1208,9 +1181,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
if (property->emit_store()) {
Node* language = jsgraph()->Constant(SLOPPY);
const Operator* op = javascript()->CallRuntime(Runtime::kSetProperty);
Node* set_property = NewNode(op, receiver, key, value, language);
// SetProperty should not lazy deopt on an object literal.
PrepareFrameState(set_property, BailoutId::None());
NewNode(op, receiver, key, value, language);
BuildSetHomeObject(value, receiver, property);
}
break;
@ -1223,22 +1194,18 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
const Operator* op =
javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Node* set_prototype = NewNode(op, receiver, value);
// SetPrototype should not lazy deopt on an object literal.
PrepareFrameState(set_prototype, expr->GetIdForPropertySet(i));
NewNode(op, receiver, value);
break;
}
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1259,8 +1226,7 @@ void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
Node* attr = jsgraph()->Constant(NONE);
const Operator* op =
javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
Node* call = NewNode(op, literal, name, getter, setter, attr);
PrepareFrameState(call, it->second->bailout_id);
NewNode(op, literal, name, getter, setter, attr);
}
ast_context()->ProduceValue(expr, environment()->Pop());
}
@ -1285,8 +1251,6 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
expr->GetOrBuildConstantElements(isolate()), expr->ComputeFlags(true),
FeedbackVector::GetIndex(expr->literal_slot()), expr->values()->length());
Node* literal = NewNode(op, closure);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
// The array is expected on the operand stack during computation of the
// element values.
@ -1305,9 +1269,7 @@ void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
Node* value = environment()->Pop();
Node* index = jsgraph()->Constant(array_index);
Node* literal = environment()->Top();
Node* store = BuildKeyedStore(literal, index, value, pair);
PrepareFrameState(store, expr->GetIdForElement(array_index),
OutputFrameStateCombine::Ignore());
BuildKeyedStore(literal, index, value, pair);
}
ast_context()->ProduceValue(expr, environment()->Pop());
@ -1319,19 +1281,11 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
// Left-hand side can only be a property, a global or a variable slot.
Property* property = expr->target()->AsProperty();
LhsKind assign_type = Property::GetAssignType(property);
bool needs_frame_state_before = true;
// Evaluate LHS expression.
switch (assign_type) {
case VARIABLE: {
Variable* variable = expr->target()->AsVariableProxy()->var();
if (variable->location() == VariableLocation::PARAMETER ||
variable->location() == VariableLocation::LOCAL ||
variable->location() == VariableLocation::CONTEXT) {
needs_frame_state_before = false;
}
case VARIABLE:
break;
}
case NAMED_PROPERTY:
VisitForValue(property->obj());
break;
@ -1354,9 +1308,7 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
VariableProxy* proxy = expr->target()->AsVariableProxy();
VectorSlotPair pair =
CreateVectorSlotPair(proxy->VariableFeedbackSlot());
PrepareEagerCheckpoint(BeforeId(proxy));
old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair,
OutputFrameStateCombine::Push());
old_value = BuildVariableLoad(proxy->var(), pair);
break;
}
case NAMED_PROPERTY: {
@ -1365,8 +1317,6 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot());
old_value = BuildNamedLoad(object, name, pair);
PrepareFrameState(old_value, property->LoadId(),
OutputFrameStateCombine::Push());
break;
}
case KEYED_PROPERTY: {
@ -1375,8 +1325,6 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot());
old_value = BuildKeyedLoad(object, key, pair);
PrepareFrameState(old_value, property->LoadId(),
OutputFrameStateCombine::Push());
break;
}
case NAMED_SUPER_PROPERTY:
@ -1388,15 +1336,8 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
VisitForValue(expr->value());
Node* right = environment()->Pop();
Node* left = environment()->Pop();
Node* value =
BuildBinaryOp(left, right, expr->binary_op(),
expr->binary_operation()->BinaryOperationFeedbackId());
PrepareFrameState(value, expr->binary_operation()->id(),
OutputFrameStateCombine::Push());
Node* value = BuildBinaryOp(left, right, expr->binary_op());
environment()->Push(value);
if (needs_frame_state_before) {
PrepareEagerCheckpoint(expr->binary_operation()->id());
}
} else {
VisitForValue(expr->value());
}
@ -1407,24 +1348,19 @@ void AstGraphBuilder::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE: {
Variable* variable = expr->target()->AsVariableProxy()->var();
BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
ast_context()->GetStateCombine());
BuildVariableAssignment(variable, value, expr->op(), feedback);
break;
}
case NAMED_PROPERTY: {
Node* object = environment()->Pop();
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Node* store = BuildNamedStore(object, name, value, feedback);
PrepareFrameState(store, expr->AssignmentId(),
OutputFrameStateCombine::Push());
BuildNamedStore(object, name, value, feedback);
break;
}
case KEYED_PROPERTY: {
Node* key = environment()->Pop();
Node* object = environment()->Pop();
Node* store = BuildKeyedStore(object, key, value, feedback);
PrepareFrameState(store, expr->AssignmentId(),
OutputFrameStateCombine::Push());
BuildKeyedStore(object, key, value, feedback);
break;
}
case NAMED_SUPER_PROPERTY:
@ -1445,7 +1381,7 @@ void AstGraphBuilder::VisitSuspend(Suspend* expr) {
void AstGraphBuilder::VisitThrow(Throw* expr) {
VisitForValue(expr->exception());
Node* exception = environment()->Pop();
Node* value = BuildThrowError(exception, expr->id());
Node* value = BuildThrowError(exception);
ast_context()->ProduceValue(expr, value);
}
@ -1463,7 +1399,6 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
Node* object = environment()->Pop();
Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
value = BuildNamedLoad(object, name, pair);
PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
break;
}
case KEYED_PROPERTY: {
@ -1472,7 +1407,6 @@ void AstGraphBuilder::VisitProperty(Property* expr) {
Node* key = environment()->Pop();
Node* object = environment()->Pop();
value = BuildKeyedLoad(object, key, pair);
PrepareFrameState(value, expr->LoadId(), OutputFrameStateCombine::Push());
break;
}
case NAMED_SUPER_PROPERTY:
@ -1498,9 +1432,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
case Call::GLOBAL_CALL: {
VariableProxy* proxy = callee->AsVariableProxy();
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
PrepareEagerCheckpoint(BeforeId(proxy));
callee_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
pair, OutputFrameStateCombine::Push());
callee_value = BuildVariableLoad(proxy->var(), pair);
receiver_hint = ConvertReceiverMode::kNullOrUndefined;
receiver_value = jsgraph()->UndefinedConstant();
break;
@ -1513,8 +1445,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Node* object = environment()->Top();
callee_value = BuildNamedLoad(object, name, feedback);
PrepareFrameState(callee_value, property->LoadId(),
OutputFrameStateCombine::Push());
// Note that a property call requires the receiver to be wrapped into
// an object for sloppy callees. However the receiver is guaranteed
// not to be null or undefined at this point.
@ -1531,8 +1461,6 @@ void AstGraphBuilder::VisitCall(Call* expr) {
Node* key = environment()->Pop();
Node* object = environment()->Top();
callee_value = BuildKeyedLoad(object, key, feedback);
PrepareFrameState(callee_value, property->LoadId(),
OutputFrameStateCombine::Push());
// Note that a property call requires the receiver to be wrapped into
// an object for sloppy callees. However the receiver is guaranteed
// not to be null or undefined at this point.
@ -1568,14 +1496,7 @@ void AstGraphBuilder::VisitCall(Call* expr) {
const Operator* call =
javascript()->Call(args->length() + 2, frequency, feedback, receiver_hint,
expr->tail_call_mode());
PrepareEagerCheckpoint(expr->CallId());
Node* value = ProcessArguments(call, args->length() + 2);
// The callee passed to the call, we just need to push something here to
// satisfy the bailout location contract. The fullcodegen code will not
// ever look at this value, so we just push optimized_out here.
environment()->Push(jsgraph()->OptimizedOutConstant());
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
environment()->Drop(1);
ast_context()->ProduceValue(expr, value);
}
@ -1596,7 +1517,6 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
const Operator* call =
javascript()->Construct(args->length() + 2, frequency, feedback);
Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->ReturnId(), OutputFrameStateCombine::Push());
ast_context()->ProduceValue(expr, value);
}
@ -1616,9 +1536,7 @@ void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
// Create node to perform the JS runtime call.
const Operator* call = javascript()->Call(args->length() + 2);
PrepareEagerCheckpoint(expr->CallId());
Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(expr, value);
}
@ -1637,12 +1555,7 @@ void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
// Create node to perform the runtime call.
Runtime::FunctionId functionId = expr->function()->function_id;
const Operator* call = javascript()->CallRuntime(functionId, args->length());
if (expr->function()->intrinsic_type == Runtime::IntrinsicType::RUNTIME ||
expr->function()->function_id == Runtime::kInlineCall) {
PrepareEagerCheckpoint(expr->CallId());
}
Node* value = ProcessArguments(call, args->length());
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(expr, value);
}
@ -1683,9 +1596,7 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
case VARIABLE: {
VariableProxy* proxy = expr->expression()->AsVariableProxy();
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
PrepareEagerCheckpoint(BeforeId(proxy));
old_value = BuildVariableLoad(proxy->var(), expr->expression()->id(),
pair, OutputFrameStateCombine::Push());
old_value = BuildVariableLoad(proxy->var(), pair);
stack_depth = 0;
break;
}
@ -1696,8 +1607,6 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot());
old_value = BuildNamedLoad(object, name, pair);
PrepareFrameState(old_value, property->LoadId(),
OutputFrameStateCombine::Push());
stack_depth = 1;
break;
}
@ -1709,8 +1618,6 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
VectorSlotPair pair =
CreateVectorSlotPair(property->PropertyFeedbackSlot());
old_value = BuildKeyedLoad(object, key, pair);
PrepareFrameState(old_value, property->LoadId(),
OutputFrameStateCombine::Push());
stack_depth = 2;
break;
}
@ -1722,12 +1629,9 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
// Convert old value into a number.
old_value = NewNode(javascript()->ToNumber(), old_value);
PrepareFrameState(old_value, expr->ToNumberId(),
OutputFrameStateCombine::Push());
// Create a proper eager frame state for the stores.
environment()->Push(old_value);
PrepareEagerCheckpoint(expr->ToNumberId());
old_value = environment()->Pop();
// Save result for postfix expressions at correct stack depth.
@ -1740,10 +1644,8 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
}
// Create node to perform +1/-1 operation.
Node* value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
expr->binary_op(), expr->CountBinOpFeedbackId());
// This should never lazy deopt because we have converted to number before.
PrepareFrameState(value, BailoutId::None());
Node* value =
BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
// Store the value.
VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
@ -1751,25 +1653,20 @@ void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
case VARIABLE: {
Variable* variable = expr->expression()->AsVariableProxy()->var();
environment()->Push(value);
BuildVariableAssignment(variable, value, expr->op(), feedback,
expr->AssignmentId());
BuildVariableAssignment(variable, value, expr->op(), feedback);
environment()->Pop();
break;
}
case NAMED_PROPERTY: {
Node* object = environment()->Pop();
Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
Node* store = BuildNamedStore(object, name, value, feedback);
PrepareFrameState(store, expr->AssignmentId(),
OutputFrameStateCombine::Push());
BuildNamedStore(object, name, value, feedback);
break;
}
case KEYED_PROPERTY: {
Node* key = environment()->Pop();
Node* object = environment()->Pop();
Node* store = BuildKeyedStore(object, key, value, feedback);
PrepareFrameState(store, expr->AssignmentId(),
OutputFrameStateCombine::Push());
BuildKeyedStore(object, key, value, feedback);
break;
}
case NAMED_SUPER_PROPERTY:
@ -1797,9 +1694,7 @@ void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
VisitForValue(expr->right());
Node* right = environment()->Pop();
Node* left = environment()->Pop();
Node* value = BuildBinaryOp(left, right, expr->op(),
expr->BinaryOperationFeedbackId());
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
Node* value = BuildBinaryOp(left, right, expr->op());
ast_context()->ProduceValue(expr, value);
}
}
@ -1822,7 +1717,6 @@ void AstGraphBuilder::VisitLiteralCompareNil(CompareOperation* expr,
VisitForValue(sub_expr);
Node* value_to_compare = environment()->Pop();
Node* value = NewNode(op, value_to_compare, nil_value);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
return ast_context()->ProduceValue(expr, value);
}
@ -1833,7 +1727,6 @@ void AstGraphBuilder::VisitLiteralCompareTypeof(CompareOperation* expr,
Node* typeof_arg = NewNode(javascript()->TypeOf(), environment()->Pop());
Node* value = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
typeof_arg, jsgraph()->Constant(check));
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
return ast_context()->ProduceValue(expr, value);
}
@ -1891,7 +1784,6 @@ void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
Node* right = environment()->Pop();
Node* left = environment()->Pop();
Node* value = NewNode(op, left, right);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(expr, value);
}
@ -1954,8 +1846,7 @@ void AstGraphBuilder::VisitDeclarations(Declaration::List* declarations) {
Node* decls = jsgraph()->Constant(data);
Node* vector = jsgraph()->Constant(feedback_vector);
const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
Node* call = NewNode(op, decls, flags, vector);
PrepareFrameState(call, BailoutId::Declarations());
NewNode(op, decls, flags, vector);
globals()->clear();
}
@ -1965,13 +1856,10 @@ void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
Visit(stmt);
}
void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
LoopBuilder* loop,
BailoutId stack_check_id) {
LoopBuilder* loop) {
ControlScopeForIteration scope(this, stmt, loop);
Node* node = NewNode(javascript()->StackCheck());
PrepareFrameState(node, stack_check_id);
NewNode(javascript()->StackCheck());
Visit(stmt->body());
}
@ -1983,8 +1871,7 @@ void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
// "delete this" is allowed.
Variable* variable = expr->expression()->AsVariableProxy()->var();
DCHECK(is_sloppy(language_mode()) || variable->is_this());
value = BuildVariableDelete(variable, expr->id(),
ast_context()->GetStateCombine());
value = BuildVariableDelete(variable);
} else if (expr->expression()->IsProperty()) {
Property* property = expr->expression()->AsProperty();
VisitForValue(property->obj());
@ -1993,7 +1880,6 @@ void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
Node* object = environment()->Pop();
Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode()));
value = NewNode(javascript()->DeleteProperty(), object, key, mode);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
} else {
VisitForEffect(expr->expression());
value = jsgraph()->TrueConstant();
@ -2014,10 +1900,7 @@ void AstGraphBuilder::VisitTypeofExpression(Expression* expr) {
// perform a non-contextual load in case the operand is a variable proxy.
VariableProxy* proxy = expr->AsVariableProxy();
VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
PrepareEagerCheckpoint(BeforeId(proxy));
Node* load =
BuildVariableLoad(proxy->var(), expr->id(), pair,
OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
Node* load = BuildVariableLoad(proxy->var(), pair, INSIDE_TYPEOF);
environment()->Push(load);
} else {
VisitForValue(expr);
@ -2065,7 +1948,7 @@ void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
if (ast_context()->IsValue()) {
VisitForValue(expr->left());
Node* left = environment()->Top();
condition = BuildToBoolean(left, expr->left()->test_id());
condition = BuildToBoolean(left);
} else {
VisitForTest(expr->left());
condition = environment()->Top();
@ -2188,8 +2071,6 @@ Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
Handle<ScopeInfo> scope_info = scope->scope_info();
const Operator* op = javascript()->CreateScriptContext(scope_info);
Node* local_context = NewNode(op, GetFunctionClosure());
PrepareFrameState(local_context, BailoutId::ScriptContext(),
OutputFrameStateCombine::Push());
return local_context;
}
@ -2217,26 +2098,23 @@ Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
: CreateArgumentsType::kMappedArguments;
const Operator* op = javascript()->CreateArguments(type);
Node* object = NewNode(op, GetFunctionClosure());
PrepareFrameState(object, BailoutId::None());
// Assign the object to the {arguments} variable. This should never lazy
// deopt, so it is fine to send invalid bailout id.
DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
BailoutId::None());
BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair());
return object;
}
Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
Node* not_hole,
BailoutId bailout_id) {
Node* not_hole) {
IfBuilder hole_check(this);
Node* the_hole = jsgraph()->TheHoleConstant();
Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
value, the_hole);
hole_check.If(check);
hole_check.Then();
Node* error = BuildThrowReferenceError(variable, bailout_id);
Node* error = BuildThrowReferenceError(variable);
environment()->Push(error);
hole_check.Else();
environment()->Push(not_hole);
@ -2244,10 +2122,8 @@ Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
return environment()->Pop();
}
Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
Node* for_hole,
BailoutId bailout_id) {
Node* for_hole) {
IfBuilder hole_check(this);
Node* the_hole = jsgraph()->TheHoleConstant();
Node* check = NewNode(javascript()->StrictEqual(CompareOperationHint::kAny),
@ -2256,16 +2132,14 @@ Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
hole_check.Then();
environment()->Push(for_hole);
hole_check.Else();
Node* error = BuildThrowReferenceError(variable, bailout_id);
Node* error = BuildThrowReferenceError(variable);
environment()->Push(error);
hole_check.End();
return environment()->Pop();
}
Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
BailoutId bailout_id,
const VectorSlotPair& feedback,
OutputFrameStateCombine combine,
TypeofMode typeof_mode) {
Node* the_hole = jsgraph()->TheHoleConstant();
switch (variable->location()) {
@ -2274,7 +2148,6 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
Handle<Name> name = variable->name();
if (Node* node = TryLoadGlobalConstant(name)) return node;
Node* value = BuildGlobalLoad(name, feedback, typeof_mode);
PrepareFrameState(value, bailout_id, combine);
return value;
}
case VariableLocation::PARAMETER:
@ -2284,9 +2157,9 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
if (variable->binding_needs_init()) {
// Perform check for uninitialized let/const variables.
if (value->op() == the_hole->op()) {
value = BuildThrowReferenceError(variable, bailout_id);
value = BuildThrowReferenceError(variable);
} else if (value->opcode() == IrOpcode::kPhi) {
value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
value = BuildHoleCheckThenThrow(value, variable, value);
}
}
return value;
@ -2307,7 +2180,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
// Maybe specializer should be a parameter to the graph builder?
if (variable->binding_needs_init()) {
// Perform check for uninitialized let/const variables.
value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
value = BuildHoleCheckThenThrow(value, variable, value);
}
return value;
}
@ -2318,10 +2191,7 @@ Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
UNREACHABLE();
}
Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
BailoutId bailout_id,
OutputFrameStateCombine combine) {
Node* AstGraphBuilder::BuildVariableDelete(Variable* variable) {
switch (variable->location()) {
case VariableLocation::UNALLOCATED: {
// Global var, const, or let variable.
@ -2330,7 +2200,6 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode()));
const Operator* op = javascript()->DeleteProperty();
Node* result = NewNode(op, global, name, mode);
PrepareFrameState(result, bailout_id, combine);
return result;
}
case VariableLocation::PARAMETER:
@ -2346,10 +2215,9 @@ Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
UNREACHABLE();
}
Node* AstGraphBuilder::BuildVariableAssignment(
Variable* variable, Node* value, Token::Value op,
const VectorSlotPair& feedback, BailoutId bailout_id,
OutputFrameStateCombine combine) {
Node* AstGraphBuilder::BuildVariableAssignment(Variable* variable, Node* value,
Token::Value op,
const VectorSlotPair& feedback) {
Node* the_hole = jsgraph()->TheHoleConstant();
VariableMode mode = variable->mode();
switch (variable->location()) {
@ -2357,7 +2225,6 @@ Node* AstGraphBuilder::BuildVariableAssignment(
// Global var, const, or let variable.
Handle<Name> name = variable->name();
Node* store = BuildGlobalStore(name, value, feedback);
PrepareFrameState(store, bailout_id, combine);
return store;
}
case VariableLocation::PARAMETER:
@ -2374,9 +2241,9 @@ Node* AstGraphBuilder::BuildVariableAssignment(
// Perform an initialization check for let declared variables.
Node* current = environment()->Lookup(variable);
if (current->op() == the_hole->op()) {
return BuildThrowReferenceError(variable, bailout_id);
return BuildThrowReferenceError(variable);
} else if (current->opcode() == IrOpcode::kPhi) {
BuildHoleCheckThenThrow(current, variable, value, bailout_id);
BuildHoleCheckThenThrow(current, variable, value);
}
} else if (mode == CONST && op == Token::INIT) {
// Perform an initialization check for const {this} variables.
@ -2384,7 +2251,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
// to trigger bind operations outside the TDZ, via {super} calls.
Node* current = environment()->Lookup(variable);
if (current->op() != the_hole->op() && variable->is_this()) {
value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
value = BuildHoleCheckElseThrow(current, variable, value);
}
} else if (mode == CONST && op != Token::INIT &&
variable->is_sloppy_function_name()) {
@ -2393,20 +2260,20 @@ Node* AstGraphBuilder::BuildVariableAssignment(
// - ignored in sloppy mode.
DCHECK(!variable->binding_needs_init());
if (variable->throw_on_const_assignment(language_mode())) {
return BuildThrowConstAssignError(bailout_id);
return BuildThrowConstAssignError();
}
return value;
} else if (mode == CONST && op != Token::INIT) {
if (variable->binding_needs_init()) {
Node* current = environment()->Lookup(variable);
if (current->op() == the_hole->op()) {
return BuildThrowReferenceError(variable, bailout_id);
return BuildThrowReferenceError(variable);
} else if (current->opcode() == IrOpcode::kPhi) {
BuildHoleCheckThenThrow(current, variable, value, bailout_id);
BuildHoleCheckThenThrow(current, variable, value);
}
}
// Assignment to const is exception in all modes.
return BuildThrowConstAssignError(bailout_id);
return BuildThrowConstAssignError();
}
environment()->Bind(variable, value);
return value;
@ -2418,7 +2285,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
const Operator* op =
javascript()->LoadContext(depth, variable->index(), false);
Node* current = NewNode(op);
value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
value = BuildHoleCheckThenThrow(current, variable, value);
} else if (mode == CONST && op == Token::INIT) {
// Perform an initialization check for const {this} variables.
// Note that the {this} variable is the only const variable being able
@ -2427,7 +2294,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
const Operator* op =
javascript()->LoadContext(depth, variable->index(), false);
Node* current = NewNode(op);
value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
value = BuildHoleCheckElseThrow(current, variable, value);
}
} else if (mode == CONST && op != Token::INIT &&
variable->is_sloppy_function_name()) {
@ -2436,7 +2303,7 @@ Node* AstGraphBuilder::BuildVariableAssignment(
// - ignored in sloppy mode.
DCHECK(!variable->binding_needs_init());
if (variable->throw_on_const_assignment(language_mode())) {
return BuildThrowConstAssignError(bailout_id);
return BuildThrowConstAssignError();
}
return value;
} else if (mode == CONST && op != Token::INIT) {
@ -2444,10 +2311,10 @@ Node* AstGraphBuilder::BuildVariableAssignment(
const Operator* op =
javascript()->LoadContext(depth, variable->index(), false);
Node* current = NewNode(op);
BuildHoleCheckThenThrow(current, variable, value, bailout_id);
BuildHoleCheckThenThrow(current, variable, value);
}
// Assignment to const is exception in all modes.
return BuildThrowConstAssignError(bailout_id);
return BuildThrowConstAssignError();
}
const Operator* op = javascript()->StoreContext(depth, variable->index());
return NewNode(op, value);
@ -2539,17 +2406,14 @@ Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
return result;
}
Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
Node* AstGraphBuilder::BuildToBoolean(Node* input) {
if (Node* node = TryFastToBoolean(input)) return node;
ToBooleanHints hints = ToBooleanHint::kAny;
return NewNode(javascript()->ToBoolean(hints), input);
}
Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
Node* AstGraphBuilder::BuildToObject(Node* input) {
Node* object = NewNode(javascript()->ToObject(), input);
PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
return object;
}
@ -2562,39 +2426,30 @@ Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
VectorSlotPair feedback =
CreateVectorSlotPair(property->GetSlot(slot_number));
Node* store = BuildNamedStore(value, name, home_object, feedback);
PrepareFrameState(store, BailoutId::None(),
OutputFrameStateCombine::Ignore());
return store;
}
Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
Node* AstGraphBuilder::BuildThrowError(Node* exception) {
const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
Node* call = NewNode(op, exception);
PrepareFrameState(call, bailout_id);
Node* control = NewNode(common()->Throw());
UpdateControlDependencyToLeaveFunction(control);
return call;
}
Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
BailoutId bailout_id) {
Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable) {
Node* variable_name = jsgraph()->Constant(variable->name());
const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
Node* call = NewNode(op, variable_name);
PrepareFrameState(call, bailout_id);
Node* control = NewNode(common()->Throw());
UpdateControlDependencyToLeaveFunction(control);
return call;
}
Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
Node* AstGraphBuilder::BuildThrowConstAssignError() {
const Operator* op =
javascript()->CallRuntime(Runtime::kThrowConstAssignError);
Node* call = NewNode(op);
PrepareFrameState(call, bailout_id);
Node* control = NewNode(common()->Throw());
UpdateControlDependencyToLeaveFunction(control);
return call;
@ -2621,9 +2476,7 @@ Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
return control;
}
Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op,
TypeFeedbackId feedback_id) {
Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
const Operator* js_op;
BinaryOperationHint hint = BinaryOperationHint::kAny;
switch (op) {
@ -2712,33 +2565,6 @@ bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
}
void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
OutputFrameStateCombine combine) {
if (OperatorProperties::HasFrameStateInput(node->op())) {
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
DCHECK_EQ(IrOpcode::kDead,
NodeProperties::GetFrameStateInput(node)->opcode());
bool has_exception = NodeProperties::IsExceptionalCall(node);
Node* state = environment()->Checkpoint(ast_id, combine, has_exception);
NodeProperties::ReplaceFrameStateInput(node, state);
}
}
void AstGraphBuilder::PrepareEagerCheckpoint(BailoutId ast_id) {
if (environment()->GetEffectDependency()->opcode() == IrOpcode::kCheckpoint) {
// We skip preparing a checkpoint if there already is one the current effect
// dependency. This is just an optimization and not need for correctness.
return;
}
if (ast_id != BailoutId::None()) {
Node* node = NewNode(common()->Checkpoint());
DCHECK_EQ(IrOpcode::kDead,
NodeProperties::GetFrameStateInput(node)->opcode());
Node* state = environment()->Checkpoint(ast_id);
NodeProperties::ReplaceFrameStateInput(node, state);
}
}
BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
IterationStatement* stmt) {
if (loop_assignment_analysis_ == nullptr) return nullptr;
@ -2784,10 +2610,8 @@ Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
*current_input++ = current_context();
}
if (has_frame_state) {
// The frame state will be inserted later. Here we misuse
// the {Dead} node as a sentinel to be later overwritten
// with the real frame state.
*current_input++ = jsgraph()->Dead();
DCHECK(!info()->is_deoptimization_enabled());
*current_input++ = GetEmptyFrameState();
}
if (has_effect) {
*current_input++ = environment_->GetEffectDependency();

View File

@ -210,18 +210,6 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
// Helper to indicate a node exits the function body.
void UpdateControlDependencyToLeaveFunction(Node* exit);
// Prepare information for lazy deoptimization. This information is attached
// to the given node and the output value produced by the node is combined.
// Conceptually this frame state is "after" a given operation.
void PrepareFrameState(Node* node, BailoutId ast_id,
OutputFrameStateCombine framestate_combine =
OutputFrameStateCombine::Ignore());
// Prepare information for eager deoptimization. This information is carried
// by dedicated {Checkpoint} nodes that are wired into the effect chain.
// Conceptually this frame state is "before" a given operation.
void PrepareEagerCheckpoint(BailoutId ast_id);
BitVector* GetVariablesAssignedInLoop(IterationStatement* stmt);
// Check if the given statement is an OSR entry.
@ -252,15 +240,9 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
// Builders for variable load and assignment.
Node* BuildVariableAssignment(Variable* variable, Node* value,
Token::Value op, const VectorSlotPair& slot,
BailoutId bailout_id,
OutputFrameStateCombine framestate_combine =
OutputFrameStateCombine::Ignore());
Node* BuildVariableDelete(Variable* variable, BailoutId bailout_id,
OutputFrameStateCombine framestate_combine);
Node* BuildVariableLoad(Variable* variable, BailoutId bailout_id,
const VectorSlotPair& feedback,
OutputFrameStateCombine framestate_combine,
Token::Value op, const VectorSlotPair& slot);
Node* BuildVariableDelete(Variable* variable);
Node* BuildVariableLoad(Variable* variable, const VectorSlotPair& feedback,
TypeofMode typeof_mode = NOT_INSIDE_TYPEOF);
// Builders for property loads and stores.
@ -286,8 +268,8 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
Node* BuildLoadNativeContextField(int index);
// Builders for automatic type conversion.
Node* BuildToBoolean(Node* input, TypeFeedbackId feedback_id);
Node* BuildToObject(Node* input, BailoutId bailout_id);
Node* BuildToBoolean(Node* input);
Node* BuildToObject(Node* input);
// Builder for adding the [[HomeObject]] to a value if the value came from a
// function literal and needs a home object. Do nothing otherwise.
@ -295,23 +277,20 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
LiteralProperty* property, int slot_number = 0);
// Builders for error reporting at runtime.
Node* BuildThrowError(Node* exception, BailoutId bailout_id);
Node* BuildThrowReferenceError(Variable* var, BailoutId bailout_id);
Node* BuildThrowConstAssignError(BailoutId bailout_id);
Node* BuildThrowError(Node* exception);
Node* BuildThrowReferenceError(Variable* var);
Node* BuildThrowConstAssignError();
// Builders for dynamic hole-checks at runtime.
Node* BuildHoleCheckThenThrow(Node* value, Variable* var, Node* not_hole,
BailoutId bailout_id);
Node* BuildHoleCheckElseThrow(Node* value, Variable* var, Node* for_hole,
BailoutId bailout_id);
Node* BuildHoleCheckThenThrow(Node* value, Variable* var, Node* not_hole);
Node* BuildHoleCheckElseThrow(Node* value, Variable* var, Node* for_hole);
// Builders for non-local control flow.
Node* BuildReturn(Node* return_value);
Node* BuildThrow(Node* exception_value);
// Builders for binary operations.
Node* BuildBinaryOp(Node* left, Node* right, Token::Value op,
TypeFeedbackId feedback_id);
Node* BuildBinaryOp(Node* left, Node* right, Token::Value op);
// Process arguments to a call by popping {arity} elements off the operand
// stack and build a call node using the given call operator.
@ -349,8 +328,7 @@ class AstGraphBuilder : public AstVisitor<AstGraphBuilder> {
void VisitForValues(ZoneList<Expression*>* exprs);
// Common for all IterationStatement bodies.
void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop,
BailoutId stack_check_id);
void VisitIterationBody(IterationStatement* stmt, LoopBuilder* loop);
// Dispatched from VisitCall.
void VisitCallSuper(Call* expr);
@ -460,12 +438,6 @@ class AstGraphBuilder::Environment : public ZoneObject {
values()->erase(values()->end() - depth, values()->end());
}
// Preserve a checkpoint of the environment for the IR graph. Any
// further mutation of the environment will not affect checkpoints.
Node* Checkpoint(BailoutId ast_id, OutputFrameStateCombine combine =
OutputFrameStateCombine::Ignore(),
bool node_has_exception = false);
// Inserts a loop exit control node and renames the environment.
// This is useful for loop peeling to insert phis at loop exits.
void PrepareForLoopExit(Node* loop, BitVector* assigned_variables);

View File

@ -32,7 +32,6 @@
#include "src/crankshaft/hydrogen-store-elimination.h"
#include "src/crankshaft/hydrogen-uint32-analysis.h"
#include "src/crankshaft/lithium-allocator.h"
#include "src/crankshaft/typing.h"
#include "src/field-type.h"
#include "src/full-codegen/full-codegen.h"
#include "src/globals.h"
@ -270,24 +269,6 @@ int HBasicBlock::LoopNestingDepth() const {
}
void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
DCHECK(IsLoopHeader());
SetJoinId(stmt->EntryId());
if (predecessors()->length() == 1) {
// This is a degenerated loop.
DetachLoopInformation();
return;
}
// Only the first entry into the loop is from outside the loop. All other
// entries must be back edges.
for (int i = 1; i < predecessors()->length(); ++i) {
loop_information()->RegisterBackEdge(predecessors()->at(i));
}
}
void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
DCHECK(IsFinished());
HBasicBlock* succ_block = end()->SuccessorAt(succ);

View File

@ -85,7 +85,6 @@ class HBasicBlock final : public ZoneObject {
void DetachLoopInformation();
bool IsLoopHeader() const { return loop_information() != NULL; }
bool IsStartBlock() const { return block_id() == 0; }
void PostProcessLoopHeader(IterationStatement* stmt);
bool IsFinished() const { return end_ != NULL; }
void AddPhi(HPhi* phi);

View File

@ -1,801 +0,0 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/crankshaft/typing.h"
#include "src/ast/compile-time-value.h"
#include "src/ast/scopes.h"
#include "src/ast/variables.h"
#include "src/frames-inl.h"
#include "src/frames.h"
#include "src/ostreams.h"
#include "src/splay-tree-inl.h"
namespace v8 {
namespace internal {
AstTyper::AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure,
DeclarationScope* scope, BailoutId osr_ast_id,
FunctionLiteral* root, AstTypeBounds* bounds)
: isolate_(isolate),
zone_(zone),
closure_(closure),
scope_(scope),
osr_ast_id_(osr_ast_id),
root_(root),
oracle_(isolate, zone, handle(closure->shared()->code()),
handle(closure->feedback_vector()),
handle(closure->context()->native_context())),
store_(zone),
bounds_(bounds) {
InitializeAstVisitor(isolate);
}
#ifdef OBJECT_PRINT
static void PrintObserved(Variable* var, Object* value, AstType* type) {
OFStream os(stdout);
os << " observed " << (var->IsParameter() ? "param" : "local") << " ";
var->name()->Print(os);
os << " : " << Brief(value) << " -> ";
type->PrintTo(os);
os << std::endl;
}
#endif // OBJECT_PRINT
Effect AstTyper::ObservedOnStack(Object* value) {
AstType* lower = AstType::NowOf(value, zone());
return Effect(AstBounds(lower, AstType::Any()));
}
void AstTyper::ObserveTypesAtOsrEntry(IterationStatement* stmt) {
if (stmt->OsrEntryId() != osr_ast_id_) return;
DisallowHeapAllocation no_gc;
JavaScriptFrameIterator it(isolate_);
JavaScriptFrame* frame = it.frame();
// Assert that the frame on the stack belongs to the function we want to OSR.
DCHECK_EQ(*closure_, frame->function());
int params = scope_->num_parameters();
int locals = scope_->StackLocalCount();
// Use sequential composition to achieve desired narrowing.
// The receiver is a parameter with index -1.
store_.Seq(parameter_index(-1), ObservedOnStack(frame->receiver()));
for (int i = 0; i < params; i++) {
store_.Seq(parameter_index(i), ObservedOnStack(frame->GetParameter(i)));
}
for (int i = 0; i < locals; i++) {
store_.Seq(stack_local_index(i), ObservedOnStack(frame->GetExpression(i)));
}
#ifdef OBJECT_PRINT
if (FLAG_trace_osr && FLAG_print_scopes) {
PrintObserved(scope_->receiver(), frame->receiver(),
store_.LookupBounds(parameter_index(-1)).lower);
for (int i = 0; i < params; i++) {
PrintObserved(scope_->parameter(i), frame->GetParameter(i),
store_.LookupBounds(parameter_index(i)).lower);
}
int local_index = 0;
for (Variable* var : *scope_->locals()) {
if (var->IsStackLocal()) {
PrintObserved(
var, frame->GetExpression(local_index),
store_.LookupBounds(stack_local_index(local_index)).lower);
local_index++;
}
}
}
#endif // OBJECT_PRINT
}
#define RECURSE(call) \
do { \
DCHECK(!HasStackOverflow()); \
call; \
if (HasStackOverflow()) return; \
} while (false)
void AstTyper::Run() {
RECURSE(VisitDeclarations(scope_->declarations()));
RECURSE(VisitStatements(root_->body()));
}
void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) {
for (int i = 0; i < stmts->length(); ++i) {
Statement* stmt = stmts->at(i);
RECURSE(Visit(stmt));
if (stmt->IsJump()) break;
}
}
void AstTyper::VisitBlock(Block* stmt) {
RECURSE(VisitStatements(stmt->statements()));
if (stmt->labels() != NULL) {
store_.Forget(); // Control may transfer here via 'break l'.
}
}
void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) {
RECURSE(Visit(stmt->expression()));
}
void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) {
}
void AstTyper::VisitSloppyBlockFunctionStatement(
SloppyBlockFunctionStatement* stmt) {
Visit(stmt->statement());
}
void AstTyper::VisitIfStatement(IfStatement* stmt) {
// Collect type feedback.
if (!stmt->condition()->ToBooleanIsTrue() &&
!stmt->condition()->ToBooleanIsFalse()) {
stmt->condition()->RecordToBooleanTypeFeedback(oracle());
}
RECURSE(Visit(stmt->condition()));
Effects then_effects = EnterEffects();
RECURSE(Visit(stmt->then_statement()));
ExitEffects();
Effects else_effects = EnterEffects();
RECURSE(Visit(stmt->else_statement()));
ExitEffects();
then_effects.Alt(else_effects);
store_.Seq(then_effects);
}
void AstTyper::VisitContinueStatement(ContinueStatement* stmt) {
// TODO(rossberg): is it worth having a non-termination effect?
}
void AstTyper::VisitBreakStatement(BreakStatement* stmt) {
// TODO(rossberg): is it worth having a non-termination effect?
}
void AstTyper::VisitReturnStatement(ReturnStatement* stmt) {
// Collect type feedback.
// TODO(rossberg): we only need this for inlining into test contexts...
stmt->expression()->RecordToBooleanTypeFeedback(oracle());
RECURSE(Visit(stmt->expression()));
// TODO(rossberg): is it worth having a non-termination effect?
}
void AstTyper::VisitWithStatement(WithStatement* stmt) {
RECURSE(stmt->expression());
RECURSE(stmt->statement());
}
void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) {
RECURSE(Visit(stmt->tag()));
ZoneList<CaseClause*>* clauses = stmt->cases();
Effects local_effects(zone());
bool complex_effects = false; // True for label effects or fall-through.
for (int i = 0; i < clauses->length(); ++i) {
CaseClause* clause = clauses->at(i);
Effects clause_effects = EnterEffects();
if (!clause->is_default()) {
Expression* label = clause->label();
// Collect type feedback.
AstType* tag_type;
AstType* label_type;
AstType* combined_type;
oracle()->CompareType(clause->CompareId(),
clause->CompareOperationFeedbackSlot(), &tag_type,
&label_type, &combined_type);
NarrowLowerType(stmt->tag(), tag_type);
NarrowLowerType(label, label_type);
clause->set_compare_type(combined_type);
RECURSE(Visit(label));
if (!clause_effects.IsEmpty()) complex_effects = true;
}
ZoneList<Statement*>* stmts = clause->statements();
RECURSE(VisitStatements(stmts));
ExitEffects();
if (stmts->is_empty() || stmts->last()->IsJump()) {
local_effects.Alt(clause_effects);
} else {
complex_effects = true;
}
}
if (complex_effects) {
store_.Forget(); // Reached this in unknown state.
} else {
store_.Seq(local_effects);
}
}
void AstTyper::VisitCaseClause(CaseClause* clause) {
UNREACHABLE();
}
void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) {
// Collect type feedback.
if (!stmt->cond()->ToBooleanIsTrue()) {
stmt->cond()->RecordToBooleanTypeFeedback(oracle());
}
// TODO(rossberg): refine the unconditional Forget (here and elsewhere) by
// computing the set of variables assigned in only some of the origins of the
// control transfer (such as the loop body here).
store_.Forget(); // Control may transfer here via looping or 'continue'.
ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body()));
RECURSE(Visit(stmt->cond()));
store_.Forget(); // Control may transfer here via 'break'.
}
void AstTyper::VisitWhileStatement(WhileStatement* stmt) {
// Collect type feedback.
if (!stmt->cond()->ToBooleanIsTrue()) {
stmt->cond()->RecordToBooleanTypeFeedback(oracle());
}
store_.Forget(); // Control may transfer here via looping or 'continue'.
RECURSE(Visit(stmt->cond()));
ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body()));
store_.Forget(); // Control may transfer here via termination or 'break'.
}
void AstTyper::VisitForStatement(ForStatement* stmt) {
if (stmt->init() != NULL) {
RECURSE(Visit(stmt->init()));
}
store_.Forget(); // Control may transfer here via looping.
if (stmt->cond() != NULL) {
// Collect type feedback.
stmt->cond()->RecordToBooleanTypeFeedback(oracle());
RECURSE(Visit(stmt->cond()));
}
ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body()));
if (stmt->next() != NULL) {
store_.Forget(); // Control may transfer here via 'continue'.
RECURSE(Visit(stmt->next()));
}
store_.Forget(); // Control may transfer here via termination or 'break'.
}
void AstTyper::VisitForInStatement(ForInStatement* stmt) {
// Collect type feedback.
stmt->set_for_in_type(static_cast<ForInStatement::ForInType>(
oracle()->ForInType(stmt->ForInFeedbackSlot())));
RECURSE(Visit(stmt->enumerable()));
store_.Forget(); // Control may transfer here via looping or 'continue'.
ObserveTypesAtOsrEntry(stmt);
RECURSE(Visit(stmt->body()));
store_.Forget(); // Control may transfer here via 'break'.
}
void AstTyper::VisitForOfStatement(ForOfStatement* stmt) {}
void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) {
Effects try_effects = EnterEffects();
RECURSE(Visit(stmt->try_block()));
ExitEffects();
Effects catch_effects = EnterEffects();
store_.Forget(); // Control may transfer here via 'throw'.
RECURSE(Visit(stmt->catch_block()));
ExitEffects();
try_effects.Alt(catch_effects);
store_.Seq(try_effects);
// At this point, only variables that were reassigned in the catch block are
// still remembered.
}
void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
RECURSE(Visit(stmt->try_block()));
store_.Forget(); // Control may transfer here via 'throw'.
RECURSE(Visit(stmt->finally_block()));
}
void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) {
store_.Forget(); // May do whatever.
}
void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) {}
void AstTyper::VisitClassLiteral(ClassLiteral* expr) {}
void AstTyper::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
}
void AstTyper::VisitDoExpression(DoExpression* expr) {
RECURSE(VisitBlock(expr->block()));
RECURSE(VisitVariableProxy(expr->result()));
NarrowType(expr, bounds_->get(expr->result()));
}
void AstTyper::VisitConditional(Conditional* expr) {
// Collect type feedback.
expr->condition()->RecordToBooleanTypeFeedback(oracle());
RECURSE(Visit(expr->condition()));
Effects then_effects = EnterEffects();
RECURSE(Visit(expr->then_expression()));
ExitEffects();
Effects else_effects = EnterEffects();
RECURSE(Visit(expr->else_expression()));
ExitEffects();
then_effects.Alt(else_effects);
store_.Seq(then_effects);
NarrowType(expr,
AstBounds::Either(bounds_->get(expr->then_expression()),
bounds_->get(expr->else_expression()), zone()));
}
void AstTyper::VisitVariableProxy(VariableProxy* expr) {
Variable* var = expr->var();
if (var->IsStackAllocated()) {
NarrowType(expr, store_.LookupBounds(variable_index(var)));
}
}
void AstTyper::VisitLiteral(Literal* expr) {
AstType* type = AstType::Constant(expr->value(), zone());
NarrowType(expr, AstBounds(type));
}
void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) {
// TODO(rossberg): Reintroduce RegExp type.
NarrowType(expr, AstBounds(AstType::Object()));
}
void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) {
ZoneList<ObjectLiteral::Property*>* properties = expr->properties();
for (int i = 0; i < properties->length(); ++i) {
ObjectLiteral::Property* prop = properties->at(i);
// Collect type feedback.
if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL &&
!CompileTimeValue::IsCompileTimeValue(prop->value())) ||
prop->kind() == ObjectLiteral::Property::COMPUTED) {
if (!prop->is_computed_name() &&
prop->key()->AsLiteral()->value()->IsInternalizedString() &&
prop->emit_store()) {
// Record type feed back for the property.
FeedbackSlot slot = prop->GetSlot();
SmallMapList maps;
oracle()->CollectReceiverTypes(slot, &maps);
prop->set_receiver_type(maps.length() == 1 ? maps.at(0)
: Handle<Map>::null());
}
}
RECURSE(Visit(prop->value()));
}
NarrowType(expr, AstBounds(AstType::Object()));
}
void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) {
ZoneList<Expression*>* values = expr->values();
for (int i = 0; i < values->length(); ++i) {
Expression* value = values->at(i);
RECURSE(Visit(value));
}
NarrowType(expr, AstBounds(AstType::Object()));
}
void AstTyper::VisitAssignment(Assignment* expr) {
// Collect type feedback.
Property* prop = expr->target()->AsProperty();
if (prop != NULL) {
FeedbackSlot slot = expr->AssignmentSlot();
expr->set_is_uninitialized(oracle()->StoreIsUninitialized(slot));
if (!expr->IsUninitialized()) {
SmallMapList* receiver_types = expr->GetReceiverTypes();
if (prop->key()->IsPropertyName()) {
Literal* lit_key = prop->key()->AsLiteral();
DCHECK(lit_key != NULL && lit_key->value()->IsString());
Handle<String> name = Handle<String>::cast(lit_key->value());
oracle()->AssignmentReceiverTypes(slot, name, receiver_types);
} else {
KeyedAccessStoreMode store_mode;
IcCheckType key_type;
oracle()->KeyedAssignmentReceiverTypes(slot, receiver_types,
&store_mode, &key_type);
expr->set_store_mode(store_mode);
expr->set_key_type(key_type);
}
}
}
Expression* rhs =
expr->is_compound() ? expr->binary_operation() : expr->value();
RECURSE(Visit(expr->target()));
RECURSE(Visit(rhs));
NarrowType(expr, bounds_->get(rhs));
VariableProxy* proxy = expr->target()->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsStackAllocated()) {
store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
}
}
void AstTyper::VisitSuspend(Suspend* expr) {
RECURSE(Visit(expr->expression()));
// We don't know anything about the result type.
}
void AstTyper::VisitThrow(Throw* expr) {
RECURSE(Visit(expr->exception()));
// TODO(rossberg): is it worth having a non-termination effect?
NarrowType(expr, AstBounds(AstType::None()));
}
void AstTyper::VisitProperty(Property* expr) {
// Collect type feedback.
FeedbackSlot slot = expr->PropertyFeedbackSlot();
expr->set_inline_cache_state(oracle()->LoadInlineCacheState(slot));
if (!expr->IsUninitialized()) {
if (expr->key()->IsPropertyName()) {
Literal* lit_key = expr->key()->AsLiteral();
DCHECK(lit_key != NULL && lit_key->value()->IsString());
Handle<String> name = Handle<String>::cast(lit_key->value());
oracle()->PropertyReceiverTypes(slot, name, expr->GetReceiverTypes());
} else {
bool is_string;
IcCheckType key_type;
oracle()->KeyedPropertyReceiverTypes(slot, expr->GetReceiverTypes(),
&is_string, &key_type);
expr->set_is_string_access(is_string);
expr->set_key_type(key_type);
}
}
RECURSE(Visit(expr->obj()));
RECURSE(Visit(expr->key()));
// We don't know anything about the result type.
}
void AstTyper::VisitCall(Call* expr) {
// Collect type feedback.
RECURSE(Visit(expr->expression()));
FeedbackSlot slot = expr->CallFeedbackICSlot();
bool is_uninitialized = oracle()->CallIsUninitialized(slot);
if (!expr->expression()->IsProperty() && oracle()->CallIsMonomorphic(slot)) {
expr->set_target(oracle()->GetCallTarget(slot));
Handle<AllocationSite> site = oracle()->GetCallAllocationSite(slot);
expr->set_allocation_site(site);
}
expr->set_is_uninitialized(is_uninitialized);
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE(Visit(arg));
}
if (expr->is_possibly_eval()) {
store_.Forget(); // Eval could do whatever to local variables.
}
// We don't know anything about the result type.
}
void AstTyper::VisitCallNew(CallNew* expr) {
// Collect type feedback.
FeedbackSlot allocation_site_feedback_slot = expr->CallNewFeedbackSlot();
expr->set_allocation_site(
oracle()->GetCallNewAllocationSite(allocation_site_feedback_slot));
bool monomorphic =
oracle()->CallNewIsMonomorphic(expr->CallNewFeedbackSlot());
expr->set_is_monomorphic(monomorphic);
if (monomorphic) {
expr->set_target(oracle()->GetCallNewTarget(expr->CallNewFeedbackSlot()));
}
RECURSE(Visit(expr->expression()));
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE(Visit(arg));
}
NarrowType(expr, AstBounds(AstType::None(), AstType::Receiver()));
}
void AstTyper::VisitCallRuntime(CallRuntime* expr) {
ZoneList<Expression*>* args = expr->arguments();
for (int i = 0; i < args->length(); ++i) {
Expression* arg = args->at(i);
RECURSE(Visit(arg));
}
// We don't know anything about the result type.
}
void AstTyper::VisitUnaryOperation(UnaryOperation* expr) {
// Collect type feedback.
if (expr->op() == Token::NOT) {
// TODO(rossberg): only do in test or value context.
expr->expression()->RecordToBooleanTypeFeedback(oracle());
}
RECURSE(Visit(expr->expression()));
switch (expr->op()) {
case Token::NOT:
case Token::DELETE:
NarrowType(expr, AstBounds(AstType::Boolean()));
break;
case Token::VOID:
NarrowType(expr, AstBounds(AstType::Undefined()));
break;
case Token::TYPEOF:
NarrowType(expr, AstBounds(AstType::InternalizedString()));
break;
default:
UNREACHABLE();
}
}
void AstTyper::VisitCountOperation(CountOperation* expr) {
// Collect type feedback.
FeedbackSlot slot = expr->CountSlot();
KeyedAccessStoreMode store_mode;
IcCheckType key_type;
oracle()->GetStoreModeAndKeyType(slot, &store_mode, &key_type);
oracle()->CountReceiverTypes(slot, expr->GetReceiverTypes());
expr->set_store_mode(store_mode);
expr->set_key_type(key_type);
expr->set_type(oracle()->CountType(expr->CountBinOpFeedbackId(),
expr->CountBinaryOpFeedbackSlot()));
// TODO(rossberg): merge the count type with the generic expression type.
RECURSE(Visit(expr->expression()));
NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
VariableProxy* proxy = expr->expression()->AsVariableProxy();
if (proxy != NULL && proxy->var()->IsStackAllocated()) {
store_.Seq(variable_index(proxy->var()), Effect(bounds_->get(expr)));
}
}
void AstTyper::VisitBinaryOperation(BinaryOperation* expr) {
// Collect type feedback.
AstType* type;
AstType* left_type;
AstType* right_type;
Maybe<int> fixed_right_arg = Nothing<int>();
Handle<AllocationSite> allocation_site;
oracle()->BinaryType(expr->BinaryOperationFeedbackId(),
expr->BinaryOperationFeedbackSlot(), &left_type,
&right_type, &type, &fixed_right_arg, &allocation_site,
expr->op());
NarrowLowerType(expr, type);
NarrowLowerType(expr->left(), left_type);
NarrowLowerType(expr->right(), right_type);
expr->set_allocation_site(allocation_site);
expr->set_fixed_right_arg(fixed_right_arg);
if (expr->op() == Token::OR || expr->op() == Token::AND) {
expr->left()->RecordToBooleanTypeFeedback(oracle());
}
switch (expr->op()) {
case Token::COMMA:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
NarrowType(expr, bounds_->get(expr->right()));
break;
case Token::OR:
case Token::AND: {
Effects left_effects = EnterEffects();
RECURSE(Visit(expr->left()));
ExitEffects();
Effects right_effects = EnterEffects();
RECURSE(Visit(expr->right()));
ExitEffects();
left_effects.Alt(right_effects);
store_.Seq(left_effects);
NarrowType(expr, AstBounds::Either(bounds_->get(expr->left()),
bounds_->get(expr->right()), zone()));
break;
}
case Token::BIT_OR:
case Token::BIT_AND: {
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
AstType* upper =
AstType::Union(bounds_->get(expr->left()).upper,
bounds_->get(expr->right()).upper, zone());
if (!upper->Is(AstType::Signed32())) upper = AstType::Signed32();
AstType* lower =
AstType::Intersect(AstType::SignedSmall(), upper, zone());
NarrowType(expr, AstBounds(lower, upper));
break;
}
case Token::BIT_XOR:
case Token::SHL:
case Token::SAR:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Signed32()));
break;
case Token::SHR:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
// TODO(rossberg): The upper bound would be Unsigned32, but since there
// is no 'positive Smi' type for the lower bound, we use the smallest
// union of Smi and Unsigned32 as upper bound instead.
NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
break;
case Token::ADD: {
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
AstBounds l = bounds_->get(expr->left());
AstBounds r = bounds_->get(expr->right());
AstType* lower =
!l.lower->IsInhabited() || !r.lower->IsInhabited()
? AstType::None()
: l.lower->Is(AstType::String()) || r.lower->Is(AstType::String())
? AstType::String()
: l.lower->Is(AstType::Number()) &&
r.lower->Is(AstType::Number())
? AstType::SignedSmall()
: AstType::None();
AstType* upper =
l.upper->Is(AstType::String()) || r.upper->Is(AstType::String())
? AstType::String()
: l.upper->Is(AstType::Number()) && r.upper->Is(AstType::Number())
? AstType::Number()
: AstType::NumberOrString();
NarrowType(expr, AstBounds(lower, upper));
break;
}
case Token::SUB:
case Token::MUL:
case Token::DIV:
case Token::MOD:
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
NarrowType(expr, AstBounds(AstType::SignedSmall(), AstType::Number()));
break;
default:
UNREACHABLE();
}
}
void AstTyper::VisitCompareOperation(CompareOperation* expr) {
// Collect type feedback.
AstType* left_type;
AstType* right_type;
AstType* combined_type;
oracle()->CompareType(expr->CompareOperationFeedbackId(),
expr->CompareOperationFeedbackSlot(), &left_type,
&right_type, &combined_type);
NarrowLowerType(expr->left(), left_type);
NarrowLowerType(expr->right(), right_type);
expr->set_combined_type(combined_type);
RECURSE(Visit(expr->left()));
RECURSE(Visit(expr->right()));
NarrowType(expr, AstBounds(AstType::Boolean()));
}
void AstTyper::VisitSpread(Spread* expr) { UNREACHABLE(); }
void AstTyper::VisitEmptyParentheses(EmptyParentheses* expr) {
UNREACHABLE();
}
void AstTyper::VisitGetIterator(GetIterator* expr) { UNREACHABLE(); }
void AstTyper::VisitImportCallExpression(ImportCallExpression* expr) {
UNREACHABLE();
}
void AstTyper::VisitThisFunction(ThisFunction* expr) {}
void AstTyper::VisitSuperPropertyReference(SuperPropertyReference* expr) {}
void AstTyper::VisitSuperCallReference(SuperCallReference* expr) {}
void AstTyper::VisitRewritableExpression(RewritableExpression* expr) {
Visit(expr->expression());
}
int AstTyper::variable_index(Variable* var) {
// Stack locals have the range [0 .. l]
// Parameters have the range [-1 .. p]
// We map this to [-p-2 .. -1, 0 .. l]
return var->IsStackLocal()
? stack_local_index(var->index())
: var->IsParameter() ? parameter_index(var->index()) : kNoVar;
}
void AstTyper::VisitDeclarations(Declaration::List* decls) {
for (Declaration* decl : *decls) {
RECURSE(Visit(decl));
}
}
void AstTyper::VisitVariableDeclaration(VariableDeclaration* declaration) {
}
void AstTyper::VisitFunctionDeclaration(FunctionDeclaration* declaration) {
RECURSE(Visit(declaration->fun()));
}
} // namespace internal
} // namespace v8

View File

@ -1,85 +0,0 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_CRANKSHAFT_TYPING_H_
#define V8_CRANKSHAFT_TYPING_H_
#include "src/allocation.h"
#include "src/ast/ast-type-bounds.h"
#include "src/ast/ast-types.h"
#include "src/ast/ast.h"
#include "src/ast/variables.h"
#include "src/effects.h"
#include "src/type-info.h"
#include "src/zone/zone.h"
namespace v8 {
namespace internal {
class DeclarationScope;
class Isolate;
class FunctionLiteral;
class AstTyper final : public AstVisitor<AstTyper> {
public:
AstTyper(Isolate* isolate, Zone* zone, Handle<JSFunction> closure,
DeclarationScope* scope, BailoutId osr_ast_id, FunctionLiteral* root,
AstTypeBounds* bounds);
void Run();
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
private:
Effect ObservedOnStack(Object* value);
void ObserveTypesAtOsrEntry(IterationStatement* stmt);
static const int kNoVar = INT_MIN;
typedef v8::internal::Effects<int, kNoVar> Effects;
typedef v8::internal::NestedEffects<int, kNoVar> Store;
Isolate* isolate_;
Zone* zone_;
Handle<JSFunction> closure_;
DeclarationScope* scope_;
BailoutId osr_ast_id_;
FunctionLiteral* root_;
TypeFeedbackOracle oracle_;
Store store_;
AstTypeBounds* bounds_;
Zone* zone() const { return zone_; }
TypeFeedbackOracle* oracle() { return &oracle_; }
void NarrowType(Expression* e, AstBounds b) {
bounds_->set(e, AstBounds::Both(bounds_->get(e), b, zone()));
}
void NarrowLowerType(Expression* e, AstType* t) {
bounds_->set(e, AstBounds::NarrowLower(bounds_->get(e), t, zone()));
}
Effects EnterEffects() {
store_ = store_.Push();
return store_.Top();
}
void ExitEffects() { store_ = store_.Pop(); }
int parameter_index(int index) { return -index - 2; }
int stack_local_index(int index) { return index; }
int variable_index(Variable* var);
void VisitDeclarations(Declaration::List* declarations);
void VisitStatements(ZoneList<Statement*>* statements);
#define DECLARE_VISIT(type) void Visit##type(type* node);
AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT
DISALLOW_COPY_AND_ASSIGN(AstTyper);
};
} // namespace internal
} // namespace v8
#endif // V8_CRANKSHAFT_TYPING_H_

View File

@ -619,7 +619,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* if_false,
Label* fall_through) {
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
Split(eq, if_true, if_false, fall_through);
}
@ -870,7 +870,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
Label skip;
@ -1244,14 +1244,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1508,7 +1506,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ jmp(&done);
@ -1582,7 +1580,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
PopOperand(r1);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
context()->Plug(r0);
}
@ -2358,7 +2356,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetExpressionPosition(expr);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ bind(&done);
@ -2543,7 +2541,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
__ cmp(r0, Operand::Zero());
Split(cond, if_true, if_false, fall_through);

View File

@ -608,7 +608,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* if_false,
Label* fall_through) {
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
Split(eq, if_true, if_false, fall_through);
}
@ -863,7 +863,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
}
@ -1225,14 +1225,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1439,7 +1437,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ Bind(&stub_call);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ B(&done);
@ -1523,7 +1521,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
JumpPatchSite patch_site(masm_); // Unbound, signals no inlined smi code.
{
Assembler::BlockPoolsScope scope(masm_);
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
}
context()->Plug(x0);
@ -2323,7 +2321,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetExpressionPosition(expr);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ Bind(&done);
@ -2519,7 +2517,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
__ CompareAndSplit(x0, 0, cond, if_true, if_false, fall_through);
}

View File

@ -829,8 +829,7 @@ void FullCodeGenerator::VisitBlock(Block* stmt) {
NestedBlock nested_block(this, stmt);
{
EnterBlockScopeIfNeeded block_scope_state(
this, stmt->scope(), stmt->EntryId(), stmt->DeclsId(), stmt->ExitId());
EnterBlockScopeIfNeeded block_scope_state(this, stmt->scope());
VisitStatements(stmt->statements());
__ bind(nested_block.break_label());
}
@ -1456,11 +1455,9 @@ bool BackEdgeTable::Verify(Isolate* isolate, Code* unoptimized) {
}
#endif // DEBUG
FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
FullCodeGenerator* codegen, Scope* scope, BailoutId entry_id,
BailoutId declarations_id, BailoutId exit_id)
: codegen_(codegen), exit_id_(exit_id) {
FullCodeGenerator* codegen, Scope* scope)
: codegen_(codegen) {
saved_scope_ = codegen_->scope();
if (scope == NULL) {

View File

@ -757,9 +757,7 @@ class FullCodeGenerator final : public AstVisitor<FullCodeGenerator> {
class EnterBlockScopeIfNeeded {
public:
EnterBlockScopeIfNeeded(FullCodeGenerator* codegen, Scope* scope,
BailoutId entry_id, BailoutId declarations_id,
BailoutId exit_id);
EnterBlockScopeIfNeeded(FullCodeGenerator* codegen, Scope* scope);
~EnterBlockScopeIfNeeded();
private:
@ -767,7 +765,6 @@ class FullCodeGenerator final : public AstVisitor<FullCodeGenerator> {
FullCodeGenerator* codegen_;
Scope* saved_scope_;
BailoutId exit_id_;
bool needs_block_context_;
};

View File

@ -565,7 +565,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* if_false,
Label* fall_through) {
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
Split(equal, if_true, if_false, fall_through);
}
@ -810,7 +810,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
Label skip;
@ -1162,14 +1162,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1421,7 +1419,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
__ mov(eax, ecx);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ jmp(&done, Label::kNear);
@ -1502,7 +1500,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
PopOperand(edx);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
context()->Plug(eax);
}
@ -2286,7 +2284,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ mov(eax, Immediate(Smi::FromInt(1)));
Handle<Code> code =
CodeFactory::BinaryOpIC(isolate(), expr->binary_op()).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ bind(&done);
@ -2473,7 +2471,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
__ test(eax, eax);

View File

@ -607,7 +607,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* fall_through) {
__ mov(a0, result_register());
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ LoadRoot(at, Heap::kTrueValueRootIndex);
Split(eq, result_register(), Operand(at), if_true, if_false, fall_through);
}
@ -862,7 +862,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
Label skip;
@ -1235,14 +1235,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1516,7 +1514,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ jmp(&done);
@ -1587,7 +1585,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
PopOperand(a1);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
context()->Plug(v0);
}
@ -2374,7 +2372,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetExpressionPosition(expr);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ bind(&done);
@ -2562,7 +2560,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
}

View File

@ -607,7 +607,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* fall_through) {
__ mov(a0, result_register());
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ LoadRoot(at, Heap::kTrueValueRootIndex);
Split(eq, result_register(), Operand(at), if_true, if_false, fall_through);
}
@ -862,7 +862,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
Label skip;
@ -1237,14 +1237,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1518,7 +1516,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ jmp(&done);
@ -1588,7 +1586,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
PopOperand(a1);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
context()->Plug(v0);
}
@ -2375,7 +2373,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetExpressionPosition(expr);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ bind(&done);
@ -2563,7 +2561,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
Split(cc, v0, Operand(zero_reg), if_true, if_false, fall_through);
}

View File

@ -591,7 +591,7 @@ void FullCodeGenerator::TestContext::Plug(bool flag) const {
void FullCodeGenerator::DoTest(Expression* condition, Label* if_true,
Label* if_false, Label* fall_through) {
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
Split(eq, if_true, if_false, fall_through);
}
@ -830,7 +830,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
Label skip;
@ -1210,14 +1210,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1485,7 +1483,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ b(&done);
@ -1591,7 +1589,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
PopOperand(r4);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
context()->Plug(r3);
}
@ -2365,7 +2363,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetExpressionPosition(expr);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ bind(&done);
@ -2553,7 +2551,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
__ cmpi(r3, Operand::Zero());
Split(cond, if_true, if_false, fall_through);

View File

@ -573,7 +573,7 @@ void FullCodeGenerator::TestContext::Plug(bool flag) const {
void FullCodeGenerator::DoTest(Expression* condition, Label* if_true,
Label* if_false, Label* fall_through) {
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
Split(eq, if_true, if_false, fall_through);
}
@ -802,7 +802,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
Label skip;
@ -1177,14 +1177,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1449,7 +1447,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ b(&done);
@ -1567,7 +1565,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
PopOperand(r3);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
context()->Plug(r2);
}
@ -2325,7 +2323,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
SetExpressionPosition(expr);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), Token::ADD).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ bind(&done);
@ -2509,7 +2507,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
__ CmpP(r2, Operand::Zero());
Split(cond, if_true, if_false, fall_through);

View File

@ -576,7 +576,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* if_false,
Label* fall_through) {
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
Split(equal, if_true, if_false, fall_through);
}
@ -823,7 +823,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
Label skip;
@ -1189,14 +1189,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1444,7 +1442,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
__ movp(rax, rcx);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ jmp(&done, Label::kNear);
@ -1491,7 +1489,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
PopOperand(rdx);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
context()->Plug(rax);
}
@ -2268,7 +2266,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ Move(rax, Smi::FromInt(1));
Handle<Code> code =
CodeFactory::BinaryOpIC(isolate(), expr->binary_op()).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ bind(&done);
@ -2455,7 +2453,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
__ testp(rax, rax);

View File

@ -560,7 +560,7 @@ void FullCodeGenerator::DoTest(Expression* condition,
Label* if_false,
Label* fall_through) {
Handle<Code> ic = ToBooleanICStub::GetUninitialized(isolate());
CallIC(ic, condition->test_id());
CallIC(ic);
__ CompareRoot(result_register(), Heap::kTrueValueRootIndex);
Split(equal, if_true, if_false, fall_through);
}
@ -800,7 +800,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
SetExpressionPosition(clause);
Handle<Code> ic =
CodeFactory::CompareIC(isolate(), Token::EQ_STRICT).code();
CallIC(ic, clause->CompareId());
CallIC(ic);
patch_site.EmitPatchInfo();
Label skip;
@ -1152,14 +1152,12 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->getter = property;
}
break;
case ObjectLiteral::Property::SETTER:
if (property->emit_store()) {
AccessorTable::Iterator it = accessor_table.lookup(key);
it->second->bailout_id = expr->GetIdForPropertySet(i);
it->second->setter = property;
}
break;
@ -1411,7 +1409,7 @@ void FullCodeGenerator::EmitInlineSmiBinaryOp(BinaryOperation* expr,
__ bind(&stub_call);
__ mov(eax, ecx);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ jmp(&done, Label::kNear);
@ -1492,7 +1490,7 @@ void FullCodeGenerator::EmitBinaryOp(BinaryOperation* expr, Token::Value op) {
PopOperand(edx);
Handle<Code> code = CodeFactory::BinaryOpIC(isolate(), op).code();
JumpPatchSite patch_site(masm_); // unbound, signals no inlined smi code.
CallIC(code, expr->BinaryOperationFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
context()->Plug(eax);
}
@ -2276,7 +2274,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
__ mov(eax, Immediate(Smi::FromInt(1)));
Handle<Code> code =
CodeFactory::BinaryOpIC(isolate(), expr->binary_op()).code();
CallIC(code, expr->CountBinOpFeedbackId());
CallIC(code);
patch_site.EmitPatchInfo();
__ bind(&done);
@ -2463,7 +2461,7 @@ void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) {
}
Handle<Code> ic = CodeFactory::CompareIC(isolate(), op).code();
CallIC(ic, expr->CompareOperationFeedbackId());
CallIC(ic);
patch_site.EmitPatchInfo();
__ test(eax, eax);

View File

@ -970,8 +970,6 @@
'crankshaft/lithium.cc',
'crankshaft/lithium.h',
'crankshaft/lithium-inl.h',
'crankshaft/typing.cc',
'crankshaft/typing.h',
'crankshaft/unique.h',
'date.cc',
'date.h',