Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/compiler/ast-graph-builder.cc b/src/compiler/ast-graph-builder.cc
index c70dfbf..abcf828 100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -206,7 +206,6 @@
int stack_height_;
};
-
// Helper class for a try-finally control scope. It can record intercepted
// control-flow commands that cause entry into a finally-block, and re-apply
// them after again leaving that block. Special tokens are used to identify
@@ -214,7 +213,10 @@
class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
public:
explicit DeferredCommands(AstGraphBuilder* owner)
- : owner_(owner), deferred_(owner->local_zone()) {}
+ : owner_(owner),
+ deferred_(owner->local_zone()),
+ return_token_(nullptr),
+ throw_token_(nullptr) {}
// One recorded control-flow command.
struct Entry {
@@ -226,7 +228,24 @@
// Records a control-flow command while entering the finally-block. This also
// generates a new dispatch token that identifies one particular path.
Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
- Node* token = NewPathTokenForDeferredCommand();
+ Node* token = nullptr;
+ switch (cmd) {
+ case CMD_BREAK:
+ case CMD_CONTINUE:
+ token = NewPathToken(dispenser_.GetBreakContinueToken());
+ break;
+ case CMD_THROW:
+ if (throw_token_) return throw_token_;
+ token = NewPathToken(TokenDispenserForFinally::kThrowToken);
+ throw_token_ = token;
+ break;
+ case CMD_RETURN:
+ if (return_token_) return return_token_;
+ token = NewPathToken(TokenDispenserForFinally::kReturnToken);
+ return_token_ = token;
+ break;
+ }
+ DCHECK_NOT_NULL(token);
deferred_.push_back({cmd, stmt, token});
return token;
}
@@ -255,11 +274,11 @@
}
protected:
- Node* NewPathTokenForDeferredCommand() {
- return owner_->jsgraph()->Constant(static_cast<int>(deferred_.size()));
+ Node* NewPathToken(int token_id) {
+ return owner_->jsgraph()->Constant(token_id);
}
Node* NewPathTokenForImplicitFallThrough() {
- return owner_->jsgraph()->Constant(-1);
+ return NewPathToken(TokenDispenserForFinally::kFallThroughToken);
}
Node* NewPathDispatchCondition(Node* t1, Node* t2) {
// TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
@@ -268,8 +287,11 @@
}
private:
+ TokenDispenserForFinally dispenser_;
AstGraphBuilder* owner_;
ZoneVector<Entry> deferred_;
+ Node* return_token_;
+ Node* throw_token_;
};
@@ -409,10 +431,13 @@
DCHECK_EQ(IrOpcode::kDead,
NodeProperties::GetFrameStateInput(node, 0)->opcode());
+ bool node_has_exception = NodeProperties::IsExceptionalCall(node);
+
Node* frame_state_after =
id_after == BailoutId::None()
? builder_->jsgraph()->EmptyFrameState()
- : builder_->environment()->Checkpoint(id_after, combine);
+ : builder_->environment()->Checkpoint(id_after, combine,
+ node_has_exception);
NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
}
@@ -455,8 +480,7 @@
local_zone),
frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
- info->scope()->num_stack_slots(), info->shared_info(),
- CALL_MAINTAINS_NATIVE_CONTEXT)) {
+ info->scope()->num_stack_slots(), info->shared_info())) {
InitializeAstVisitor(info->isolate());
}
@@ -589,7 +613,7 @@
// Emit tracing call if requested to do so.
if (FLAG_trace) {
- NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0));
+ NewNode(javascript()->CallRuntime(Runtime::kTraceEnter));
}
// Visit illegal re-declaration and bail out if it exists.
@@ -610,13 +634,6 @@
// Visit statements in the function body.
VisitStatements(info()->literal()->body());
- // Emit tracing call if requested to do so.
- if (FLAG_trace) {
- // TODO(mstarzinger): Only traces implicit return.
- Node* return_value = jsgraph()->UndefinedConstant();
- NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
- }
-
// Return 'undefined' in case we can fall off the end.
BuildReturn(jsgraph()->UndefinedConstant());
}
@@ -854,9 +871,9 @@
env_values, static_cast<size_t>(count));
}
-
-Node* AstGraphBuilder::Environment::Checkpoint(
- BailoutId ast_id, OutputFrameStateCombine combine) {
+Node* AstGraphBuilder::Environment::Checkpoint(BailoutId ast_id,
+ OutputFrameStateCombine combine,
+ bool owner_has_exception) {
if (!builder()->info()->is_deoptimization_enabled()) {
return builder()->jsgraph()->EmptyFrameState();
}
@@ -876,7 +893,15 @@
DCHECK(IsLivenessBlockConsistent());
if (liveness_block() != nullptr) {
- liveness_block()->Checkpoint(result);
+ // If the owning node has an exception, register the checkpoint to the
+ // predecessor so that the checkpoint is used for both the normal and the
+ // exceptional paths. Yes, this is a terrible hack and we might want
+ // to use an explicit frame state for the exceptional path.
+ if (owner_has_exception) {
+ liveness_block()->GetPredecessor()->Checkpoint(result);
+ } else {
+ liveness_block()->Checkpoint(result);
+ }
}
return result;
}
@@ -1331,7 +1356,8 @@
// Prepare for-in cache.
Node* prepare = NewNode(javascript()->ForInPrepare(), object);
- PrepareFrameState(prepare, stmt->EnumId(), OutputFrameStateCombine::Push());
+ PrepareFrameState(prepare, stmt->PrepareId(),
+ OutputFrameStateCombine::Push(3));
Node* cache_type = NewNode(common()->Projection(0), prepare);
Node* cache_array = NewNode(common()->Projection(1), prepare);
Node* cache_length = NewNode(common()->Projection(2), prepare);
@@ -1422,14 +1448,6 @@
}
try_control.EndTry();
- // Insert lazy bailout point.
- // TODO(mstarzinger): We are only using a 'call' to get a lazy bailout
- // point. Ideally, we whould not re-enter optimized code when deoptimized
- // lazily. Tracked by issue v8:4195.
- NewNode(common()->LazyBailout(),
- jsgraph()->ZeroConstant(), // dummy target.
- environment()->Checkpoint(stmt->HandlerId())); // frame state.
-
// Clear message object as we enter the catch block.
Node* the_hole = jsgraph()->TheHoleConstant();
NewNode(javascript()->StoreMessage(), the_hole);
@@ -1474,14 +1492,6 @@
}
try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
- // Insert lazy bailout point.
- // TODO(mstarzinger): We are only using a 'call' to get a lazy bailout
- // point. Ideally, we whould not re-enter optimized code when deoptimized
- // lazily. Tracked by issue v8:4195.
- NewNode(common()->LazyBailout(),
- jsgraph()->ZeroConstant(), // dummy target.
- environment()->Checkpoint(stmt->HandlerId())); // frame state.
-
// The result value semantics depend on how the block was entered:
// - ReturnStatement: It represents the return value being returned.
// - ThrowStatement: It represents the exception being thrown.
@@ -1493,7 +1503,7 @@
// The result value, dispatch token and message is expected on the operand
// stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
Node* message = NewNode(javascript()->LoadMessage());
- environment()->Push(token); // TODO(mstarzinger): Cook token!
+ environment()->Push(token);
environment()->Push(result);
environment()->Push(message);
@@ -1509,20 +1519,17 @@
// stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
message = environment()->Pop();
result = environment()->Pop();
- token = environment()->Pop(); // TODO(mstarzinger): Uncook token!
+ token = environment()->Pop();
NewNode(javascript()->StoreMessage(), message);
// Dynamic dispatch after the finally-block.
commands->ApplyDeferredCommands(token, result);
-
- // TODO(mstarzinger): Remove bailout once everything works.
- if (!FLAG_turbo_try_finally) SetStackOverflow();
}
void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
Node* node =
- NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement, 0));
+ NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
PrepareFrameState(node, stmt->DebugBreakId());
environment()->MarkAllLocalsLive();
}
@@ -1557,33 +1564,27 @@
void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
- Node* class_name = expr->raw_name() ? jsgraph()->Constant(expr->name())
- : jsgraph()->UndefinedConstant();
-
- // The class name is expected on the operand stack.
- environment()->Push(class_name);
VisitForValueOrTheHole(expr->extends());
VisitForValue(expr->constructor());
// Create node to instantiate a new class.
Node* constructor = environment()->Pop();
Node* extends = environment()->Pop();
- Node* name = environment()->Pop();
Node* start = jsgraph()->Constant(expr->start_position());
Node* end = jsgraph()->Constant(expr->end_position());
- const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 5);
- Node* literal = NewNode(opc, name, extends, constructor, start, end);
+ const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass);
+ Node* literal = NewNode(opc, extends, constructor, start, end);
PrepareFrameState(literal, expr->CreateLiteralId(),
OutputFrameStateCombine::Push());
-
- // The prototype is ensured to exist by Runtime_DefineClass. No access check
- // is needed here since the constructor is created by the class literal.
- Node* prototype =
- BuildLoadObjectField(literal, JSFunction::kPrototypeOrInitialMapOffset);
-
- // The class literal and the prototype are both expected on the operand stack
- // during evaluation of the method values.
environment()->Push(literal);
+
+ // Load the "prototype" from the constructor.
+ FrameStateBeforeAndAfter states(this, expr->CreateLiteralId());
+ Handle<Name> name = isolate()->factory()->prototype_string();
+ VectorSlotPair pair = CreateVectorSlotPair(expr->PrototypeSlot());
+ Node* prototype = BuildNamedLoad(literal, name, pair);
+ states.AddToNode(prototype, expr->PrototypeId(),
+ OutputFrameStateCombine::Push());
environment()->Push(prototype);
// Create nodes to store method values into the literal.
@@ -1618,9 +1619,12 @@
case ObjectLiteral::Property::PROTOTYPE:
UNREACHABLE();
case ObjectLiteral::Property::COMPUTED: {
+ Node* attr = jsgraph()->Constant(DONT_ENUM);
+ Node* set_function_name =
+ jsgraph()->Constant(property->NeedsSetFunctionName());
const Operator* op =
- javascript()->CallRuntime(Runtime::kDefineClassMethod, 3);
- NewNode(op, receiver, key, value);
+ javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
+ NewNode(op, receiver, key, value, attr, set_function_name);
break;
}
case ObjectLiteral::Property::GETTER: {
@@ -1645,7 +1649,7 @@
prototype = environment()->Pop();
literal = environment()->Pop();
const Operator* op =
- javascript()->CallRuntime(Runtime::kFinalizeClassDefinition, 2);
+ javascript()->CallRuntime(Runtime::kFinalizeClassDefinition);
literal = NewNode(op, literal, prototype);
// Assign to class variable.
@@ -1774,8 +1778,7 @@
Node* receiver = environment()->Pop();
if (property->emit_store()) {
Node* language = jsgraph()->Constant(SLOPPY);
- const Operator* op =
- javascript()->CallRuntime(Runtime::kSetProperty, 4);
+ 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());
@@ -1790,7 +1793,7 @@
Node* receiver = environment()->Pop();
DCHECK(property->emit_store());
const Operator* op =
- javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
+ javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Node* set_prototype = NewNode(op, receiver, value);
// SetPrototype should not lazy deopt on an object literal.
PrepareFrameState(set_prototype,
@@ -1823,7 +1826,7 @@
Node* name = environment()->Pop();
Node* attr = jsgraph()->Constant(NONE);
const Operator* op =
- javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
+ javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked);
Node* call = NewNode(op, literal, name, getter, setter, attr);
// This should not lazy deopt on a new literal.
PrepareFrameState(call, BailoutId::None());
@@ -1847,7 +1850,7 @@
Node* value = environment()->Pop();
Node* receiver = environment()->Pop();
const Operator* op =
- javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
+ javascript()->CallRuntime(Runtime::kInternalSetPrototype);
Node* call = NewNode(op, receiver, value);
PrepareFrameState(call, expr->GetIdForPropertySet(property_index));
continue;
@@ -1868,10 +1871,11 @@
case ObjectLiteral::Property::COMPUTED:
case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
Node* attr = jsgraph()->Constant(NONE);
+ Node* set_function_name =
+ jsgraph()->Constant(property->NeedsSetFunctionName());
const Operator* op =
- javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
- Node* call = NewNode(op, receiver, key, value, attr);
- PrepareFrameState(call, BailoutId::None());
+ javascript()->CallRuntime(Runtime::kDefineDataPropertyInLiteral);
+ NewNode(op, receiver, key, value, attr, set_function_name);
break;
}
case ObjectLiteral::Property::PROTOTYPE:
@@ -1899,8 +1903,7 @@
// Transform literals that contain functions to fast properties.
literal = environment()->Top(); // Reload from operand stack.
if (expr->has_function()) {
- const Operator* op =
- javascript()->CallRuntime(Runtime::kToFastProperties, 1);
+ const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties);
NewNode(op, literal);
}
@@ -1939,7 +1942,7 @@
int array_index = 0;
for (; array_index < expr->values()->length(); array_index++) {
Expression* subexpr = expr->values()->at(array_index);
- if (subexpr->IsSpread()) break;
+ DCHECK(!subexpr->IsSpread());
if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
VisitForValue(subexpr);
@@ -1962,30 +1965,17 @@
// number elements an iterable produces is unknown ahead of time.
for (; array_index < expr->values()->length(); array_index++) {
Expression* subexpr = expr->values()->at(array_index);
- Node* result;
+ DCHECK(!subexpr->IsSpread());
- if (subexpr->IsSpread()) {
- VisitForValue(subexpr->AsSpread()->expression());
- FrameStateBeforeAndAfter states(this,
- subexpr->AsSpread()->expression()->id());
- Node* iterable = environment()->Pop();
- Node* array = environment()->Pop();
- Node* function = BuildLoadNativeContextField(
- Context::CONCAT_ITERABLE_TO_ARRAY_BUILTIN_INDEX);
- result = NewNode(javascript()->CallFunction(3, language_mode()), function,
- array, iterable);
- states.AddToNode(result, expr->GetIdForElement(array_index));
- } else {
- VisitForValue(subexpr);
+ VisitForValue(subexpr);
+ {
Node* value = environment()->Pop();
Node* array = environment()->Pop();
- const Operator* op =
- javascript()->CallRuntime(Runtime::kAppendElement, 2);
- result = NewNode(op, array, value);
+ const Operator* op = javascript()->CallRuntime(Runtime::kAppendElement);
+ Node* result = NewNode(op, array, value);
PrepareFrameState(result, expr->GetIdForElement(array_index));
+ environment()->Push(result);
}
-
- environment()->Push(result);
}
ast_context()->ProduceValue(environment()->Pop());
@@ -2343,8 +2333,8 @@
DCHECK(variable->location() == VariableLocation::LOOKUP);
Node* name = jsgraph()->Constant(variable->name());
const Operator* op =
- javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
- Node* pair = NewNode(op, current_context(), name);
+ javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
+ Node* pair = NewNode(op, name);
callee_value = NewNode(common()->Projection(0), pair);
receiver_value = NewNode(common()->Projection(1), pair);
PrepareFrameState(pair, expr->LookupId(),
@@ -2439,8 +2429,8 @@
Variable* variable = callee->AsVariableProxy()->var();
Node* name = jsgraph()->Constant(variable->name());
const Operator* op =
- javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
- Node* pair = NewNode(op, current_context(), name);
+ javascript()->CallRuntime(Runtime::kLoadLookupSlotForCall);
+ Node* pair = NewNode(op, name);
callee_value = NewNode(common()->Projection(0), pair);
receiver_value = NewNode(common()->Projection(1), pair);
PrepareFrameState(pair, expr->LookupId(),
@@ -2480,7 +2470,7 @@
Node* language = jsgraph()->Constant(language_mode());
Node* position = jsgraph()->Constant(current_scope()->start_position());
const Operator* op =
- javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
+ javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval);
Node* new_callee =
NewNode(op, callee, source, function, language, position);
PrepareFrameState(new_callee, expr->EvalId(),
@@ -2493,7 +2483,7 @@
// Create node to perform the function call.
VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
const Operator* call = javascript()->CallFunction(
- args->length() + 2, language_mode(), feedback, receiver_hint);
+ args->length() + 2, feedback, receiver_hint, expr->tail_call_mode());
FrameStateBeforeAndAfter states(this, expr->CallId());
Node* value = ProcessArguments(call, args->length() + 2);
environment()->Push(value->InputAt(0)); // The callee passed to the call.
@@ -2571,8 +2561,7 @@
VisitForValues(args);
// Create node to perform the JS runtime call.
- const Operator* call =
- javascript()->CallFunction(args->length() + 2, language_mode());
+ const Operator* call = javascript()->CallFunction(args->length() + 2);
FrameStateBeforeAndAfter states(this, expr->CallId());
Node* value = ProcessArguments(call, args->length() + 2);
states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
@@ -2591,6 +2580,7 @@
// TODO(mstarzinger): This bailout is a gigantic hack, the owner is ashamed.
if (function->function_id == Runtime::kInlineGeneratorNext ||
+ function->function_id == Runtime::kInlineGeneratorReturn ||
function->function_id == Runtime::kInlineGeneratorThrow) {
ast_context()->ProduceValue(jsgraph()->TheHoleConstant());
return SetStackOverflow();
@@ -2740,7 +2730,7 @@
// TODO(bmeurer): Cleanup this feedback/bailout mess!
FrameStateBeforeAndAfter states(this, BailoutId::None());
value = BuildBinaryOp(old_value, jsgraph()->OneConstant(),
- expr->binary_op(), TypeFeedbackId::None());
+ expr->binary_op(), expr->CountBinOpFeedbackId());
// This should never deoptimize outside strong mode because otherwise we
// have converted to number before.
states.AddToNode(value, is_strong(language_mode()) ? expr->ToNumberId()
@@ -2848,16 +2838,16 @@
op = javascript()->StrictNotEqual();
break;
case Token::LT:
- op = javascript()->LessThan(language_mode());
+ op = javascript()->LessThan();
break;
case Token::GT:
- op = javascript()->GreaterThan(language_mode());
+ op = javascript()->GreaterThan();
break;
case Token::LTE:
- op = javascript()->LessThanOrEqual(language_mode());
+ op = javascript()->LessThanOrEqual();
break;
case Token::GTE:
- op = javascript()->GreaterThanOrEqual(language_mode());
+ op = javascript()->GreaterThanOrEqual();
break;
case Token::INSTANCEOF:
op = javascript()->InstanceOf();
@@ -2930,7 +2920,7 @@
DeclareGlobalsLanguageMode::encode(language_mode());
Node* flags = jsgraph()->Constant(encoded_flags);
Node* pairs = jsgraph()->Constant(data);
- const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals, 2);
+ const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals);
Node* call = NewNode(op, pairs, flags);
PrepareFrameState(call, BailoutId::Declarations());
globals()->clear();
@@ -3072,8 +3062,7 @@
}
-void AstGraphBuilder::VisitRewritableAssignmentExpression(
- RewritableAssignmentExpression* node) {
+void AstGraphBuilder::VisitRewritableExpression(RewritableExpression* node) {
Visit(node->expression());
}
@@ -3209,11 +3198,11 @@
if (arguments == nullptr) return nullptr;
// Allocate and initialize a new arguments object.
- CreateArgumentsParameters::Type type =
+ CreateArgumentsType type =
is_strict(language_mode()) || !info()->has_simple_parameters()
- ? CreateArgumentsParameters::kUnmappedArguments
- : CreateArgumentsParameters::kMappedArguments;
- const Operator* op = javascript()->CreateArguments(type, 0);
+ ? CreateArgumentsType::kUnmappedArguments
+ : CreateArgumentsType::kMappedArguments;
+ const Operator* op = javascript()->CreateArguments(type);
Node* object = NewNode(op, GetFunctionClosure());
PrepareFrameState(object, BailoutId::None());
@@ -3231,8 +3220,8 @@
if (rest == nullptr) return nullptr;
// Allocate and initialize a new arguments object.
- CreateArgumentsParameters::Type type = CreateArgumentsParameters::kRestArray;
- const Operator* op = javascript()->CreateArguments(type, index);
+ CreateArgumentsType type = CreateArgumentsType::kRestParameter;
+ const Operator* op = javascript()->CreateArguments(type);
Node* object = NewNode(op, GetFunctionClosure());
PrepareFrameState(object, BailoutId::None());
@@ -3405,8 +3394,7 @@
feedback, combine, typeof_mode)) {
return node;
}
- const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
- Node* value = NewNode(op, BuildLoadFeedbackVector(), current_context());
+ Node* value = BuildDynamicLoad(name, typeof_mode);
states.AddToNode(value, bailout_id, combine);
return value;
}
@@ -3440,8 +3428,8 @@
// Dynamic lookup of context variable (anywhere in the chain).
Node* name = jsgraph()->Constant(variable->name());
const Operator* op =
- javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
- Node* result = NewNode(op, current_context(), name);
+ javascript()->CallRuntime(Runtime::kDeleteLookupSlot);
+ Node* result = NewNode(op, name);
PrepareFrameState(result, bailout_id, combine);
return result;
}
@@ -3563,13 +3551,10 @@
}
case VariableLocation::LOOKUP: {
// Dynamic lookup of context variable (anywhere in the chain).
- Node* name = jsgraph()->Constant(variable->name());
- Node* language = jsgraph()->Constant(language_mode());
+ Handle<Name> name = variable->name();
// TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
// initializations of const declarations.
- const Operator* op =
- javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
- Node* store = NewNode(op, value, current_context(), name, language);
+ Node* store = BuildDynamicStore(name, value);
PrepareFrameState(store, bailout_id, combine);
return store;
}
@@ -3581,16 +3566,16 @@
Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
const VectorSlotPair& feedback) {
- const Operator* op = javascript()->LoadProperty(language_mode(), feedback);
- Node* node = NewNode(op, object, key, BuildLoadFeedbackVector());
+ const Operator* op = javascript()->LoadProperty(feedback);
+ Node* node = NewNode(op, object, key, GetFunctionClosure());
return node;
}
Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
const VectorSlotPair& feedback) {
- const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback);
- Node* node = NewNode(op, object, BuildLoadFeedbackVector());
+ const Operator* op = javascript()->LoadNamed(name, feedback);
+ Node* node = NewNode(op, object, GetFunctionClosure());
return node;
}
@@ -3598,7 +3583,7 @@
Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
const VectorSlotPair& feedback) {
const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
- Node* node = NewNode(op, object, key, value, BuildLoadFeedbackVector());
+ Node* node = NewNode(op, object, key, value, GetFunctionClosure());
return node;
}
@@ -3608,7 +3593,7 @@
const VectorSlotPair& feedback) {
const Operator* op =
javascript()->StoreNamed(language_mode(), name, feedback);
- Node* node = NewNode(op, object, value, BuildLoadFeedbackVector());
+ Node* node = NewNode(op, object, value, GetFunctionClosure());
return node;
}
@@ -3617,9 +3602,8 @@
Handle<Name> name,
const VectorSlotPair& feedback) {
Node* name_node = jsgraph()->Constant(name);
- Node* language = jsgraph()->Constant(language_mode());
- const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 4);
- Node* node = NewNode(op, receiver, home_object, name_node, language);
+ const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper);
+ Node* node = NewNode(op, receiver, home_object, name_node);
return node;
}
@@ -3627,10 +3611,8 @@
Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
Node* key,
const VectorSlotPair& feedback) {
- Node* language = jsgraph()->Constant(language_mode());
- const Operator* op =
- javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
- Node* node = NewNode(op, receiver, home_object, key, language);
+ const Operator* op = javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper);
+ Node* node = NewNode(op, receiver, home_object, key);
return node;
}
@@ -3662,7 +3644,7 @@
const VectorSlotPair& feedback,
TypeofMode typeof_mode) {
const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
- Node* node = NewNode(op, BuildLoadFeedbackVector());
+ Node* node = NewNode(op, GetFunctionClosure());
return node;
}
@@ -3671,22 +3653,30 @@
const VectorSlotPair& feedback) {
const Operator* op =
javascript()->StoreGlobal(language_mode(), name, feedback);
- Node* node = NewNode(op, value, BuildLoadFeedbackVector());
+ Node* node = NewNode(op, value, GetFunctionClosure());
return node;
}
-Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
- return NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), object,
- jsgraph()->IntPtrConstant(offset - kHeapObjectTag));
+Node* AstGraphBuilder::BuildDynamicLoad(Handle<Name> name,
+ TypeofMode typeof_mode) {
+ Node* name_node = jsgraph()->Constant(name);
+ const Operator* op =
+ javascript()->CallRuntime(typeof_mode == TypeofMode::NOT_INSIDE_TYPEOF
+ ? Runtime::kLoadLookupSlot
+ : Runtime::kLoadLookupSlotInsideTypeof);
+ Node* node = NewNode(op, name_node);
+ return node;
}
-Node* AstGraphBuilder::BuildLoadImmutableObjectField(Node* object, int offset) {
- return graph()->NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()),
- object,
- jsgraph()->IntPtrConstant(offset - kHeapObjectTag),
- graph()->start(), graph()->start());
+Node* AstGraphBuilder::BuildDynamicStore(Handle<Name> name, Node* value) {
+ Node* name_node = jsgraph()->Constant(name);
+ const Operator* op = javascript()->CallRuntime(
+ is_strict(language_mode()) ? Runtime::kStoreLookupSlot_Strict
+ : Runtime::kStoreLookupSlot_Sloppy);
+ Node* node = NewNode(op, name_node, value);
+ return node;
}
@@ -3703,19 +3693,6 @@
}
-Node* AstGraphBuilder::BuildLoadFeedbackVector() {
- if (!feedback_vector_.is_set()) {
- Node* closure = GetFunctionClosure();
- Node* shared = BuildLoadImmutableObjectField(
- closure, JSFunction::kSharedFunctionInfoOffset);
- Node* vector = BuildLoadImmutableObjectField(
- shared, SharedFunctionInfo::kFeedbackVectorOffset);
- feedback_vector_.set(vector);
- }
- return feedback_vector_.get();
-}
-
-
Node* AstGraphBuilder::BuildToBoolean(Node* input, TypeFeedbackId feedback_id) {
if (Node* node = TryFastToBoolean(input)) return node;
ToBooleanHints hints;
@@ -3758,7 +3735,7 @@
Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
- const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
+ const Operator* op = javascript()->CallRuntime(Runtime::kThrow);
Node* call = NewNode(op, exception);
PrepareFrameState(call, bailout_id);
Node* control = NewNode(common()->Throw(), call);
@@ -3770,8 +3747,7 @@
Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
BailoutId bailout_id) {
Node* variable_name = jsgraph()->Constant(variable->name());
- const Operator* op =
- javascript()->CallRuntime(Runtime::kThrowReferenceError, 1);
+ const Operator* op = javascript()->CallRuntime(Runtime::kThrowReferenceError);
Node* call = NewNode(op, variable_name);
PrepareFrameState(call, bailout_id);
Node* control = NewNode(common()->Throw(), call);
@@ -3782,7 +3758,7 @@
Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
const Operator* op =
- javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0);
+ javascript()->CallRuntime(Runtime::kThrowConstAssignError);
Node* call = NewNode(op);
PrepareFrameState(call, bailout_id);
Node* control = NewNode(common()->Throw(), call);
@@ -3793,7 +3769,7 @@
Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
const Operator* op =
- javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError, 0);
+ javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError);
Node* call = NewNode(op);
PrepareFrameState(call, bailout_id);
Node* control = NewNode(common()->Throw(), call);
@@ -3804,7 +3780,7 @@
Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
const Operator* op =
- javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
+ javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError);
Node* call = NewNode(op);
PrepareFrameState(call, bailout_id);
Node* control = NewNode(common()->Throw(), call);
@@ -3814,6 +3790,11 @@
Node* AstGraphBuilder::BuildReturn(Node* return_value) {
+ // Emit tracing call if requested to do so.
+ if (FLAG_trace) {
+ return_value =
+ NewNode(javascript()->CallRuntime(Runtime::kTraceExit), return_value);
+ }
Node* control = NewNode(common()->Return(), return_value);
UpdateControlDependencyToLeaveFunction(control);
return control;
@@ -3821,7 +3802,7 @@
Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
- NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), exception_value);
+ NewNode(javascript()->CallRuntime(Runtime::kReThrow), exception_value);
Node* control = NewNode(common()->Throw(), exception_value);
UpdateControlDependencyToLeaveFunction(control);
return control;
@@ -3838,37 +3819,37 @@
}
switch (op) {
case Token::BIT_OR:
- js_op = javascript()->BitwiseOr(language_mode(), hints);
+ js_op = javascript()->BitwiseOr(hints);
break;
case Token::BIT_AND:
- js_op = javascript()->BitwiseAnd(language_mode(), hints);
+ js_op = javascript()->BitwiseAnd(hints);
break;
case Token::BIT_XOR:
- js_op = javascript()->BitwiseXor(language_mode(), hints);
+ js_op = javascript()->BitwiseXor(hints);
break;
case Token::SHL:
- js_op = javascript()->ShiftLeft(language_mode(), hints);
+ js_op = javascript()->ShiftLeft(hints);
break;
case Token::SAR:
- js_op = javascript()->ShiftRight(language_mode(), hints);
+ js_op = javascript()->ShiftRight(hints);
break;
case Token::SHR:
- js_op = javascript()->ShiftRightLogical(language_mode(), hints);
+ js_op = javascript()->ShiftRightLogical(hints);
break;
case Token::ADD:
- js_op = javascript()->Add(language_mode(), hints);
+ js_op = javascript()->Add(hints);
break;
case Token::SUB:
- js_op = javascript()->Subtract(language_mode(), hints);
+ js_op = javascript()->Subtract(hints);
break;
case Token::MUL:
- js_op = javascript()->Multiply(language_mode(), hints);
+ js_op = javascript()->Multiply(hints);
break;
case Token::DIV:
- js_op = javascript()->Divide(language_mode(), hints);
+ js_op = javascript()->Divide(hints);
break;
case Token::MOD:
- js_op = javascript()->Modulus(language_mode(), hints);
+ js_op = javascript()->Modulus(hints);
break;
default:
UNREACHABLE();
@@ -3916,17 +3897,21 @@
fast_block.BreakUnless(check, BranchHint::kTrue);
}
- // Fast case, because variable is not shadowed. Perform global slot load.
- Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
- states.AddToNode(fast, bailout_id, combine);
- environment()->Push(fast);
+ // Fast case, because variable is not shadowed.
+ if (Node* constant = TryLoadGlobalConstant(name)) {
+ environment()->Push(constant);
+ } else {
+ // Perform global slot load.
+ Node* fast = BuildGlobalLoad(name, feedback, typeof_mode);
+ states.AddToNode(fast, bailout_id, combine);
+ environment()->Push(fast);
+ }
slow_block.Break();
environment()->Pop();
fast_block.EndBlock();
// Slow case, because variable potentially shadowed. Perform dynamic lookup.
- const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
- Node* slow = NewNode(op, BuildLoadFeedbackVector(), current_context());
+ Node* slow = BuildDynamicLoad(name, typeof_mode);
states.AddToNode(slow, bailout_id, combine);
environment()->Push(slow);
slow_block.EndBlock();
@@ -3969,8 +3954,7 @@
fast_block.EndBlock();
// Slow case, because variable potentially shadowed. Perform dynamic lookup.
- const Operator* op = javascript()->LoadDynamic(name, typeof_mode);
- Node* slow = NewNode(op, BuildLoadFeedbackVector(), current_context());
+ Node* slow = BuildDynamicLoad(name, typeof_mode);
states.AddToNode(slow, bailout_id, combine);
environment()->Push(slow);
slow_block.EndBlock();
@@ -4047,8 +4031,10 @@
DCHECK_EQ(IrOpcode::kDead,
NodeProperties::GetFrameStateInput(node, 0)->opcode());
+ bool node_has_exception = NodeProperties::IsExceptionalCall(node);
NodeProperties::ReplaceFrameStateInput(
- node, 0, environment()->Checkpoint(ast_id, combine));
+ node, 0,
+ environment()->Checkpoint(ast_id, combine, node_has_exception));
}
}