[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:
parent
f626d5df7e
commit
bc717ae84b
2
BUILD.gn
2
BUILD.gn
@ -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",
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
283
src/ast/ast.h
283
src/ast/ast.h
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
@ -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_
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user