Commit aeb41de0 authored by bmeurer's avatar bmeurer Committed by Commit bot

[turbofan] Initial support for Array constructor specialization.

Introduce a JSCreateArray operator that represents the Array
constructor, and lower call and construct calls to the Array
constructor to JSCreateArray. Currently we don't yet replace
that with an inline allocation, but always use the specialized
stubs for the Array constructor.

This saves a lot of unnecessary deopts and elements transitions
because now we can actually consume the allocation site feedback
for the transitions.

R=mstarzinger@chromium.org
BUG=v8:4470
LOG=n

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

Cr-Commit-Position: refs/heads/master@{#32145}
parent 2fc2cb99
...@@ -2512,7 +2512,8 @@ void AstGraphBuilder::VisitCallSuper(Call* expr) { ...@@ -2512,7 +2512,8 @@ void AstGraphBuilder::VisitCallSuper(Call* expr) {
VisitForValue(super->new_target_var()); VisitForValue(super->new_target_var());
// Create node to perform the super call. // Create node to perform the super call.
const Operator* call = javascript()->CallConstruct(args->length() + 2); const Operator* call =
javascript()->CallConstruct(args->length() + 2, VectorSlotPair());
Node* value = ProcessArguments(call, args->length() + 2); Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value); ast_context()->ProduceValue(value);
...@@ -2530,7 +2531,9 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) { ...@@ -2530,7 +2531,9 @@ void AstGraphBuilder::VisitCallNew(CallNew* expr) {
environment()->Push(environment()->Peek(args->length())); environment()->Push(environment()->Peek(args->length()));
// Create node to perform the construct call. // Create node to perform the construct call.
const Operator* call = javascript()->CallConstruct(args->length() + 2); VectorSlotPair feedback = CreateVectorSlotPair(expr->CallNewFeedbackSlot());
const Operator* call =
javascript()->CallConstruct(args->length() + 2, feedback);
Node* value = ProcessArguments(call, args->length() + 2); Node* value = ProcessArguments(call, args->length() + 2);
PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine()); PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
ast_context()->ProduceValue(value); ast_context()->ProduceValue(value);
...@@ -3652,8 +3655,7 @@ Node* AstGraphBuilder::BuildLoadGlobalObject() { ...@@ -3652,8 +3655,7 @@ Node* AstGraphBuilder::BuildLoadGlobalObject() {
Node* AstGraphBuilder::BuildLoadNativeContextField(int index) { Node* AstGraphBuilder::BuildLoadNativeContextField(int index) {
Node* global = BuildLoadGlobalObject(); Node* global = BuildLoadGlobalObject();
Node* native_context = Node* native_context = NewNode(javascript()->LoadNativeContext(), global);
BuildLoadObjectField(global, JSGlobalObject::kNativeContextOffset);
return NewNode(javascript()->LoadContext(0, index, true), native_context); return NewNode(javascript()->LoadContext(0, index, true), native_context);
} }
......
...@@ -792,8 +792,9 @@ void BytecodeGraphBuilder::VisitNew( ...@@ -792,8 +792,9 @@ void BytecodeGraphBuilder::VisitNew(
interpreter::Register first_arg = iterator.GetRegisterOperand(1); interpreter::Register first_arg = iterator.GetRegisterOperand(1);
size_t arg_count = iterator.GetCountOperand(2); size_t arg_count = iterator.GetCountOperand(2);
const Operator* call = // TODO(turbofan): Pass the feedback here.
javascript()->CallConstruct(static_cast<int>(arg_count) + 2); const Operator* call = javascript()->CallConstruct(
static_cast<int>(arg_count) + 2, VectorSlotPair());
Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2); Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2);
AddEmptyFrameStateInputs(value); AddEmptyFrameStateInputs(value);
environment()->BindAccumulator(value); environment()->BindAccumulator(value);
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "src/compiler/js-graph.h" #include "src/compiler/js-graph.h"
#include "src/compiler/node-matchers.h" #include "src/compiler/node-matchers.h"
#include "src/compiler/simplified-operator.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
#include "src/type-feedback-vector-inl.h" #include "src/type-feedback-vector-inl.h"
...@@ -40,6 +39,8 @@ VectorSlotPair CallCountFeedback(VectorSlotPair p) { ...@@ -40,6 +39,8 @@ VectorSlotPair CallCountFeedback(VectorSlotPair p) {
Reduction JSCallReducer::Reduce(Node* node) { Reduction JSCallReducer::Reduce(Node* node) {
switch (node->opcode()) { switch (node->opcode()) {
case IrOpcode::kJSCallConstruct:
return ReduceJSCallConstruct(node);
case IrOpcode::kJSCallFunction: case IrOpcode::kJSCallFunction:
return ReduceJSCallFunction(node); return ReduceJSCallFunction(node);
default: default:
...@@ -49,6 +50,36 @@ Reduction JSCallReducer::Reduce(Node* node) { ...@@ -49,6 +50,36 @@ Reduction JSCallReducer::Reduce(Node* node) {
} }
// ES6 section 22.1.1 The Array Constructor
Reduction JSCallReducer::ReduceArrayConstructor(Node* node) {
Node* target = NodeProperties::GetValueInput(node, 0);
DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
// Check if we have an allocation site from the CallIC.
Handle<AllocationSite> site;
if (p.feedback().IsValid()) {
CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
Handle<Object> feedback(nexus.GetFeedback(), isolate());
if (feedback->IsAllocationSite()) {
site = Handle<AllocationSite>::cast(feedback);
}
}
// Turn the {node} into a {JSCreateArray} call.
DCHECK_LE(2u, p.arity());
size_t const arity = p.arity() - 2;
NodeProperties::ReplaceValueInput(node, target, 0);
NodeProperties::ReplaceValueInput(node, target, 1);
NodeProperties::RemoveFrameStateInput(node, 1);
// TODO(bmeurer): We might need to propagate the tail call mode to
// the JSCreateArray operator, because an Array call in tail call
// position must always properly consume the parent stack frame.
NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site));
return Changed(node);
}
// ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray ) // ES6 section 19.2.3.1 Function.prototype.apply ( thisArg, argArray )
Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) { Reduction JSCallReducer::ReduceFunctionPrototypeApply(Node* node) {
DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
...@@ -170,6 +201,7 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { ...@@ -170,6 +201,7 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode()); DCHECK_EQ(IrOpcode::kJSCallFunction, node->opcode());
CallFunctionParameters const& p = CallFunctionParametersOf(node->op()); CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
Node* target = NodeProperties::GetValueInput(node, 0); Node* target = NodeProperties::GetValueInput(node, 0);
Node* context = NodeProperties::GetContextInput(node);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 1); Node* frame_state = NodeProperties::GetFrameStateInput(node, 1);
Node* control = NodeProperties::GetControlInput(node); Node* control = NodeProperties::GetControlInput(node);
Node* effect = NodeProperties::GetEffectInput(node); Node* effect = NodeProperties::GetEffectInput(node);
...@@ -178,8 +210,8 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { ...@@ -178,8 +210,8 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
HeapObjectMatcher m(target); HeapObjectMatcher m(target);
if (m.HasValue()) { if (m.HasValue()) {
if (m.Value()->IsJSFunction()) { if (m.Value()->IsJSFunction()) {
Handle<SharedFunctionInfo> shared( Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
Handle<JSFunction>::cast(m.Value())->shared(), isolate()); Handle<SharedFunctionInfo> shared(function->shared(), isolate());
// Raise a TypeError if the {target} is a "classConstructor". // Raise a TypeError if the {target} is a "classConstructor".
if (IsClassConstructor(shared->kind())) { if (IsClassConstructor(shared->kind())) {
...@@ -202,7 +234,13 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { ...@@ -202,7 +234,13 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
break; break;
} }
} }
// Check for the ArrayConstructor.
if (*function == function->native_context()->array_function()) {
return ReduceArrayConstructor(node);
}
} }
// Don't mess with other {node}s that have a constant {target}. // Don't mess with other {node}s that have a constant {target}.
// TODO(bmeurer): Also support optimizing bound functions and proxies here. // TODO(bmeurer): Also support optimizing bound functions and proxies here.
return NoChange(); return NoChange();
...@@ -215,14 +253,52 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { ...@@ -215,14 +253,52 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
if (!p.feedback().IsValid()) return NoChange(); if (!p.feedback().IsValid()) return NoChange();
CallICNexus nexus(p.feedback().vector(), p.feedback().slot()); CallICNexus nexus(p.feedback().vector(), p.feedback().slot());
Handle<Object> feedback(nexus.GetFeedback(), isolate()); Handle<Object> feedback(nexus.GetFeedback(), isolate());
if (feedback->IsWeakCell()) { if (feedback->IsAllocationSite()) {
// Retrieve the Array function from the {node}.
Node* array_function;
Handle<Context> native_context;
if (GetNativeContext(node).ToHandle(&native_context)) {
array_function = jsgraph()->HeapConstant(
handle(native_context->array_function(), isolate()));
} else {
Node* global_object = effect = graph()->NewNode(
javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true),
context, context, effect);
Node* native_context = effect = graph()->NewNode(
javascript()->LoadNativeContext(), global_object, context, effect);
array_function = effect = graph()->NewNode(
javascript()->LoadContext(0, Context::ARRAY_FUNCTION_INDEX, true),
native_context, native_context, effect);
}
// Check that the {target} is still the {array_function}.
Node* check = effect =
graph()->NewNode(javascript()->StrictEqual(), target, array_function,
context, effect, control);
Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* deoptimize =
graph()->NewNode(common()->Deoptimize(), frame_state, effect, if_false);
// TODO(bmeurer): This should be on the AdvancedReducer somehow.
NodeProperties::MergeControlToEnd(graph(), common(), deoptimize);
control = graph()->NewNode(common()->IfTrue(), branch);
// Turn the {node} into a {JSCreateArray} call.
NodeProperties::ReplaceValueInput(node, array_function, 0);
NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control);
return ReduceArrayConstructor(node);
} else if (feedback->IsWeakCell()) {
Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback); Handle<WeakCell> cell = Handle<WeakCell>::cast(feedback);
if (cell->value()->IsJSFunction()) { if (cell->value()->IsJSFunction()) {
Node* target_function =
jsgraph()->Constant(handle(cell->value(), isolate()));
// Check that the {target} is still the {target_function}. // Check that the {target} is still the {target_function}.
Node* target_function = jsgraph()->HeapConstant( Node* check = effect =
handle(JSFunction::cast(cell->value()), isolate())); graph()->NewNode(javascript()->StrictEqual(), target, target_function,
Node* check = graph()->NewNode(simplified()->ReferenceEqual(Type::Any()), context, effect, control);
target, target_function);
Node* branch = Node* branch =
graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
Node* if_false = graph()->NewNode(common()->IfFalse(), branch); Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
...@@ -234,6 +310,7 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { ...@@ -234,6 +310,7 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
// Specialize the JSCallFunction node to the {target_function}. // Specialize the JSCallFunction node to the {target_function}.
NodeProperties::ReplaceValueInput(node, target_function, 0); NodeProperties::ReplaceValueInput(node, target_function, 0);
NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control); NodeProperties::ReplaceControlInput(node, control);
// Try to further reduce the JSCallFunction {node}. // Try to further reduce the JSCallFunction {node}.
...@@ -245,6 +322,68 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) { ...@@ -245,6 +322,68 @@ Reduction JSCallReducer::ReduceJSCallFunction(Node* node) {
} }
Reduction JSCallReducer::ReduceJSCallConstruct(Node* node) {
DCHECK_EQ(IrOpcode::kJSCallConstruct, node->opcode());
CallConstructParameters const& p = CallConstructParametersOf(node->op());
DCHECK_LE(2u, p.arity());
int const arity = static_cast<int>(p.arity() - 2);
Node* target = NodeProperties::GetValueInput(node, 0);
Node* new_target = NodeProperties::GetValueInput(node, arity + 1);
// Try to specialize JSCallConstruct {node}s with constant {target}s.
HeapObjectMatcher m(target);
if (m.HasValue()) {
if (m.Value()->IsJSFunction()) {
Handle<JSFunction> function = Handle<JSFunction>::cast(m.Value());
// Raise a TypeError if the {target} is not a constructor.
if (!function->IsConstructor()) {
NodeProperties::ReplaceValueInputs(node, target);
NodeProperties::ChangeOp(
node,
javascript()->CallRuntime(Runtime::kThrowCalledNonCallable, 1));
return Changed(node);
}
// Check for the ArrayConstructor.
if (*function == function->native_context()->array_function()) {
// Check if we have an allocation site.
Handle<AllocationSite> site;
if (p.feedback().IsValid()) {
Handle<Object> feedback(
p.feedback().vector()->Get(p.feedback().slot()), isolate());
if (feedback->IsAllocationSite()) {
site = Handle<AllocationSite>::cast(feedback);
}
}
// Turn the {node} into a {JSCreateArray} call.
for (int i = arity; i > 0; --i) {
NodeProperties::ReplaceValueInput(
node, NodeProperties::GetValueInput(node, i), i + 1);
}
NodeProperties::ReplaceValueInput(node, new_target, 1);
NodeProperties::ChangeOp(node, javascript()->CreateArray(arity, site));
return Changed(node);
}
}
// Don't mess with other {node}s that have a constant {target}.
// TODO(bmeurer): Also support optimizing bound functions and proxies here.
return NoChange();
}
return NoChange();
}
MaybeHandle<Context> JSCallReducer::GetNativeContext(Node* node) {
Node* const context = NodeProperties::GetContextInput(node);
return NodeProperties::GetSpecializationNativeContext(context,
native_context());
}
Graph* JSCallReducer::graph() const { return jsgraph()->graph(); } Graph* JSCallReducer::graph() const { return jsgraph()->graph(); }
...@@ -260,11 +399,6 @@ JSOperatorBuilder* JSCallReducer::javascript() const { ...@@ -260,11 +399,6 @@ JSOperatorBuilder* JSCallReducer::javascript() const {
return jsgraph()->javascript(); return jsgraph()->javascript();
} }
SimplifiedOperatorBuilder* JSCallReducer::simplified() const {
return jsgraph()->simplified();
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -16,11 +16,10 @@ namespace compiler { ...@@ -16,11 +16,10 @@ namespace compiler {
class CommonOperatorBuilder; class CommonOperatorBuilder;
class JSGraph; class JSGraph;
class JSOperatorBuilder; class JSOperatorBuilder;
class SimplifiedOperatorBuilder;
// Performs strength reduction on {JSCallFunction} nodes, which might allow // Performs strength reduction on {JSCallConstruct} and {JSCallFunction} nodes,
// inlining or other optimizations to be performed afterwards. // which might allow inlining or other optimizations to be performed afterwards.
class JSCallReducer final : public Reducer { class JSCallReducer final : public Reducer {
public: public:
// Flags that control the mode of operation. // Flags that control the mode of operation.
...@@ -30,26 +29,32 @@ class JSCallReducer final : public Reducer { ...@@ -30,26 +29,32 @@ class JSCallReducer final : public Reducer {
}; };
typedef base::Flags<Flag> Flags; typedef base::Flags<Flag> Flags;
JSCallReducer(JSGraph* jsgraph, Flags flags) JSCallReducer(JSGraph* jsgraph, Flags flags,
: jsgraph_(jsgraph), flags_(flags) {} MaybeHandle<Context> native_context)
: jsgraph_(jsgraph), flags_(flags), native_context_(native_context) {}
Reduction Reduce(Node* node) final; Reduction Reduce(Node* node) final;
private: private:
Reduction ReduceArrayConstructor(Node* node);
Reduction ReduceFunctionPrototypeApply(Node* node); Reduction ReduceFunctionPrototypeApply(Node* node);
Reduction ReduceFunctionPrototypeCall(Node* node); Reduction ReduceFunctionPrototypeCall(Node* node);
Reduction ReduceJSCallConstruct(Node* node);
Reduction ReduceJSCallFunction(Node* node); Reduction ReduceJSCallFunction(Node* node);
MaybeHandle<Context> GetNativeContext(Node* node);
Graph* graph() const; Graph* graph() const;
Flags flags() const { return flags_; } Flags flags() const { return flags_; }
JSGraph* jsgraph() const { return jsgraph_; } JSGraph* jsgraph() const { return jsgraph_; }
Isolate* isolate() const; Isolate* isolate() const;
MaybeHandle<Context> native_context() const { return native_context_; }
CommonOperatorBuilder* common() const; CommonOperatorBuilder* common() const;
JSOperatorBuilder* javascript() const; JSOperatorBuilder* javascript() const;
SimplifiedOperatorBuilder* simplified() const;
JSGraph* const jsgraph_; JSGraph* const jsgraph_;
Flags const flags_; Flags const flags_;
MaybeHandle<Context> const native_context_;
}; };
DEFINE_OPERATORS_FOR_FLAGS(JSCallReducer::Flags) DEFINE_OPERATORS_FOR_FLAGS(JSCallReducer::Flags)
......
...@@ -429,6 +429,15 @@ void JSGenericLowering::LowerJSStoreContext(Node* node) { ...@@ -429,6 +429,15 @@ void JSGenericLowering::LowerJSStoreContext(Node* node) {
} }
void JSGenericLowering::LowerJSLoadNativeContext(Node* node) {
node->ReplaceInput(
1, jsgraph()->IntPtrConstant(JSGlobalObject::kNativeContextOffset -
kHeapObjectTag));
node->AppendInput(zone(), graph()->start());
NodeProperties::ChangeOp(node, machine()->Load(kMachAnyTagged));
}
void JSGenericLowering::LowerJSLoadDynamic(Node* node) { void JSGenericLowering::LowerJSLoadDynamic(Node* node) {
const DynamicAccess& access = DynamicAccessOf(node->op()); const DynamicAccess& access = DynamicAccessOf(node->op());
Runtime::FunctionId function_id = Runtime::FunctionId function_id =
...@@ -465,6 +474,26 @@ void JSGenericLowering::LowerJSCreateArguments(Node* node) { ...@@ -465,6 +474,26 @@ void JSGenericLowering::LowerJSCreateArguments(Node* node) {
} }
void JSGenericLowering::LowerJSCreateArray(Node* node) {
CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
int const arity = static_cast<int>(p.arity());
Node* new_target = node->InputAt(1);
// TODO(turbofan): We embed the AllocationSite from the Operator at this
// point, which we should not do once we want to both consume the feedback
// but at the same time shared the optimized code across native contexts,
// as the AllocationSite is associated with a single native context (it's
// stored in the type feedback vector after all). Once we go for cross
// context code generation, we should somehow find a way to get to the
// allocation site for the actual native context at runtime.
Node* type_info = p.site().is_null() ? jsgraph()->UndefinedConstant()
: jsgraph()->HeapConstant(p.site());
node->RemoveInput(1);
node->InsertInput(zone(), 1 + arity, new_target);
node->InsertInput(zone(), 2 + arity, type_info);
ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
}
void JSGenericLowering::LowerJSCreateClosure(Node* node) { void JSGenericLowering::LowerJSCreateClosure(Node* node) {
CreateClosureParameters p = CreateClosureParametersOf(node->op()); CreateClosureParameters p = CreateClosureParametersOf(node->op());
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.shared_info())); node->InsertInput(zone(), 0, jsgraph()->HeapConstant(p.shared_info()));
...@@ -510,8 +539,9 @@ void JSGenericLowering::LowerJSCreateScriptContext(Node* node) { ...@@ -510,8 +539,9 @@ void JSGenericLowering::LowerJSCreateScriptContext(Node* node) {
void JSGenericLowering::LowerJSCallConstruct(Node* node) { void JSGenericLowering::LowerJSCallConstruct(Node* node) {
CallConstructParameters const& p = CallConstructParametersOf(node->op());
int const arity = static_cast<int>(p.arity());
// TODO(bmeurer): Use the Construct builtin here. // TODO(bmeurer): Use the Construct builtin here.
int arity = OpParameter<int>(node);
CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL); CallConstructStub stub(isolate(), SUPER_CONSTRUCTOR_CALL);
CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor(); CallInterfaceDescriptor d = stub.GetCallInterfaceDescriptor();
CallDescriptor::Flags flags = AdjustFrameStatesForCall(node); CallDescriptor::Flags flags = AdjustFrameStatesForCall(node);
......
...@@ -63,6 +63,34 @@ std::ostream& operator<<(std::ostream& os, TailCallMode mode) { ...@@ -63,6 +63,34 @@ std::ostream& operator<<(std::ostream& os, TailCallMode mode) {
} }
bool operator==(CallConstructParameters const& lhs,
CallConstructParameters const& rhs) {
return lhs.arity() == rhs.arity() && lhs.feedback() == rhs.feedback();
}
bool operator!=(CallConstructParameters const& lhs,
CallConstructParameters const& rhs) {
return !(lhs == rhs);
}
size_t hash_value(CallConstructParameters const& p) {
return base::hash_combine(p.arity(), p.feedback());
}
std::ostream& operator<<(std::ostream& os, CallConstructParameters const& p) {
return os << p.arity();
}
CallConstructParameters const& CallConstructParametersOf(Operator const* op) {
DCHECK_EQ(IrOpcode::kJSCallConstruct, op->opcode());
return OpParameter<CallConstructParameters>(op);
}
std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) { std::ostream& operator<<(std::ostream& os, CallFunctionParameters const& p) {
os << p.arity() << ", " << p.language_mode() << ", " << p.convert_mode() os << p.arity() << ", " << p.language_mode() << ", " << p.convert_mode()
<< ", " << p.tail_call_mode(); << ", " << p.tail_call_mode();
...@@ -322,6 +350,37 @@ const CreateArgumentsParameters& CreateArgumentsParametersOf( ...@@ -322,6 +350,37 @@ const CreateArgumentsParameters& CreateArgumentsParametersOf(
} }
bool operator==(CreateArrayParameters const& lhs,
CreateArrayParameters const& rhs) {
return lhs.arity() == rhs.arity() &&
lhs.site().location() == rhs.site().location();
}
bool operator!=(CreateArrayParameters const& lhs,
CreateArrayParameters const& rhs) {
return !(lhs == rhs);
}
size_t hash_value(CreateArrayParameters const& p) {
return base::hash_combine(p.arity(), p.site().location());
}
std::ostream& operator<<(std::ostream& os, CreateArrayParameters const& p) {
os << p.arity();
if (!p.site().is_null()) os << ", " << Brief(*p.site());
return os;
}
const CreateArrayParameters& CreateArrayParametersOf(const Operator* op) {
DCHECK_EQ(IrOpcode::kJSCreateArray, op->opcode());
return OpParameter<CreateArrayParameters>(op);
}
bool operator==(CreateClosureParameters const& lhs, bool operator==(CreateClosureParameters const& lhs,
CreateClosureParameters const& rhs) { CreateClosureParameters const& rhs) {
return lhs.pretenure() == rhs.pretenure() && return lhs.pretenure() == rhs.pretenure() &&
...@@ -374,6 +433,7 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) { ...@@ -374,6 +433,7 @@ const CreateClosureParameters& CreateClosureParametersOf(const Operator* op) {
V(LoadMessage, Operator::kNoThrow, 0, 1) \ V(LoadMessage, Operator::kNoThrow, 0, 1) \
V(StoreMessage, Operator::kNoThrow, 1, 0) \ V(StoreMessage, Operator::kNoThrow, 1, 0) \
V(StackCheck, Operator::kNoProperties, 0, 0) \ V(StackCheck, Operator::kNoProperties, 0, 0) \
V(LoadNativeContext, Operator::kEliminatable, 1, 1) \
V(CreateWithContext, Operator::kNoProperties, 2, 1) \ V(CreateWithContext, Operator::kNoProperties, 2, 1) \
V(CreateModuleContext, Operator::kNoProperties, 2, 1) V(CreateModuleContext, Operator::kNoProperties, 2, 1)
...@@ -493,12 +553,14 @@ const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id, ...@@ -493,12 +553,14 @@ const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
} }
const Operator* JSOperatorBuilder::CallConstruct(int arguments) { const Operator* JSOperatorBuilder::CallConstruct(
return new (zone()) Operator1<int>( // -- size_t arity, VectorSlotPair const& feedback) {
CallConstructParameters parameters(arity, feedback);
return new (zone()) Operator1<CallConstructParameters>( // --
IrOpcode::kJSCallConstruct, Operator::kNoProperties, // opcode IrOpcode::kJSCallConstruct, Operator::kNoProperties, // opcode
"JSCallConstruct", // name "JSCallConstruct", // name
arguments, 1, 1, 1, 1, 2, // counts parameters.arity(), 1, 1, 1, 1, 2, // counts
arguments); // parameter parameters); // parameter
} }
...@@ -637,6 +699,19 @@ const Operator* JSOperatorBuilder::CreateArguments( ...@@ -637,6 +699,19 @@ const Operator* JSOperatorBuilder::CreateArguments(
} }
const Operator* JSOperatorBuilder::CreateArray(size_t arity,
Handle<AllocationSite> site) {
// constructor, new_target, arg1, ..., argN
int const value_input_count = static_cast<int>(arity) + 2;
CreateArrayParameters parameters(arity, site);
return new (zone()) Operator1<CreateArrayParameters>( // --
IrOpcode::kJSCreateArray, Operator::kNoProperties, // opcode
"JSCreateArray", // name
value_input_count, 1, 1, 1, 1, 2, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::CreateClosure( const Operator* JSOperatorBuilder::CreateClosure(
Handle<SharedFunctionInfo> shared_info, PretenureFlag pretenure) { Handle<SharedFunctionInfo> shared_info, PretenureFlag pretenure) {
CreateClosureParameters parameters(shared_info, pretenure); CreateClosureParameters parameters(shared_info, pretenure);
......
...@@ -54,6 +54,31 @@ size_t hash_value(TailCallMode); ...@@ -54,6 +54,31 @@ size_t hash_value(TailCallMode);
std::ostream& operator<<(std::ostream&, TailCallMode); std::ostream& operator<<(std::ostream&, TailCallMode);
// Defines the arity and the feedback for a JavaScript constructor call. This is
// used as a parameter by JSCallConstruct operators.
class CallConstructParameters final {
public:
CallConstructParameters(size_t arity, VectorSlotPair const& feedback)
: arity_(arity), feedback_(feedback) {}
size_t arity() const { return arity_; }
VectorSlotPair const& feedback() const { return feedback_; }
private:
size_t const arity_;
VectorSlotPair const feedback_;
};
bool operator==(CallConstructParameters const&, CallConstructParameters const&);
bool operator!=(CallConstructParameters const&, CallConstructParameters const&);
size_t hash_value(CallConstructParameters const&);
std::ostream& operator<<(std::ostream&, CallConstructParameters const&);
CallConstructParameters const& CallConstructParametersOf(Operator const*);
// Defines the arity and the call flags for a JavaScript function call. This is // Defines the arity and the call flags for a JavaScript function call. This is
// used as a parameter by JSCallFunction operators. // used as a parameter by JSCallFunction operators.
class CallFunctionParameters final { class CallFunctionParameters final {
...@@ -327,6 +352,31 @@ const CreateArgumentsParameters& CreateArgumentsParametersOf( ...@@ -327,6 +352,31 @@ const CreateArgumentsParameters& CreateArgumentsParametersOf(
const Operator* op); const Operator* op);
// Defines shared information for the array that should be created. This is
// used as parameter by JSCreateArray operators.
class CreateArrayParameters final {
public:
explicit CreateArrayParameters(size_t arity, Handle<AllocationSite> site)
: arity_(arity), site_(site) {}
size_t arity() const { return arity_; }
Handle<AllocationSite> site() const { return site_; }
private:
size_t const arity_;
Handle<AllocationSite> const site_;
};
bool operator==(CreateArrayParameters const&, CreateArrayParameters const&);
bool operator!=(CreateArrayParameters const&, CreateArrayParameters const&);
size_t hash_value(CreateArrayParameters const&);
std::ostream& operator<<(std::ostream&, CreateArrayParameters const&);
const CreateArrayParameters& CreateArrayParametersOf(const Operator* op);
// Defines shared information for the closure that should be created. This is // Defines shared information for the closure that should be created. This is
// used as a parameter by JSCreateClosure operators. // used as a parameter by JSCreateClosure operators.
class CreateClosureParameters final { class CreateClosureParameters final {
...@@ -391,6 +441,7 @@ class JSOperatorBuilder final : public ZoneObject { ...@@ -391,6 +441,7 @@ class JSOperatorBuilder final : public ZoneObject {
const Operator* Create(); const Operator* Create();
const Operator* CreateArguments(CreateArgumentsParameters::Type type, const Operator* CreateArguments(CreateArgumentsParameters::Type type,
int start_index); int start_index);
const Operator* CreateArray(size_t arity, Handle<AllocationSite> site);
const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info, const Operator* CreateClosure(Handle<SharedFunctionInfo> shared_info,
PretenureFlag pretenure); PretenureFlag pretenure);
const Operator* CreateLiteralArray(int literal_flags); const Operator* CreateLiteralArray(int literal_flags);
...@@ -402,7 +453,7 @@ class JSOperatorBuilder final : public ZoneObject { ...@@ -402,7 +453,7 @@ class JSOperatorBuilder final : public ZoneObject {
ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny, ConvertReceiverMode convert_mode = ConvertReceiverMode::kAny,
TailCallMode tail_call_mode = TailCallMode::kDisallow); TailCallMode tail_call_mode = TailCallMode::kDisallow);
const Operator* CallRuntime(Runtime::FunctionId id, size_t arity); const Operator* CallRuntime(Runtime::FunctionId id, size_t arity);
const Operator* CallConstruct(int arguments); const Operator* CallConstruct(size_t arity, VectorSlotPair const& feedback);
const Operator* ConvertReceiver(ConvertReceiverMode convert_mode); const Operator* ConvertReceiver(ConvertReceiverMode convert_mode);
...@@ -430,6 +481,8 @@ class JSOperatorBuilder final : public ZoneObject { ...@@ -430,6 +481,8 @@ class JSOperatorBuilder final : public ZoneObject {
const Operator* LoadContext(size_t depth, size_t index, bool immutable); const Operator* LoadContext(size_t depth, size_t index, bool immutable);
const Operator* StoreContext(size_t depth, size_t index); const Operator* StoreContext(size_t depth, size_t index);
const Operator* LoadNativeContext();
const Operator* LoadDynamic(const Handle<String>& name, const Operator* LoadDynamic(const Handle<String>& name,
TypeofMode typeof_mode); TypeofMode typeof_mode);
......
...@@ -1232,6 +1232,19 @@ Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) { ...@@ -1232,6 +1232,19 @@ Reduction JSTypedLowering::ReduceJSStoreContext(Node* node) {
} }
Reduction JSTypedLowering::ReduceJSLoadNativeContext(Node* node) {
DCHECK_EQ(IrOpcode::kJSLoadNativeContext, node->opcode());
Node* const effect = NodeProperties::GetEffectInput(node);
Node* const control = graph()->start();
node->ReplaceInput(1, effect);
node->ReplaceInput(2, control);
NodeProperties::ChangeOp(
node,
simplified()->LoadField(AccessBuilder::ForJSGlobalObjectNativeContext()));
return Changed(node);
}
Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) { Reduction JSTypedLowering::ReduceJSConvertReceiver(Node* node) {
DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode()); DCHECK_EQ(IrOpcode::kJSConvertReceiver, node->opcode());
ConvertReceiverMode mode = ConvertReceiverModeOf(node->op()); ConvertReceiverMode mode = ConvertReceiverModeOf(node->op());
...@@ -1548,6 +1561,69 @@ Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) { ...@@ -1548,6 +1561,69 @@ Reduction JSTypedLowering::ReduceJSCreateArguments(Node* node) {
} }
Reduction JSTypedLowering::ReduceJSCreateArray(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateArray, node->opcode());
CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
Node* const target = NodeProperties::GetValueInput(node, 0);
Node* const new_target = NodeProperties::GetValueInput(node, 1);
// TODO(bmeurer): Optimize the subclassing case.
if (target != new_target) return NoChange();
// Check if we have a feedback {site} on the {node}.
Handle<AllocationSite> site = p.site();
if (p.site().is_null()) return NoChange();
ElementsKind const elements_kind = site->GetElementsKind();
AllocationSiteOverrideMode override_mode =
(AllocationSite::GetMode(elements_kind) == TRACK_ALLOCATION_SITE)
? DISABLE_ALLOCATION_SITES
: DONT_OVERRIDE;
// Reduce {node} to the appropriate ArrayConstructorStub backend.
// Note that these stubs "behave" like JSFunctions, which means they
// expect a receiver on the stack, which they remove. We just push
// undefined for the receiver.
if (p.arity() == 0) {
ArrayNoArgumentConstructorStub stub(isolate(), elements_kind,
override_mode);
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 1,
CallDescriptor::kNeedsFrameState);
node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
node->InsertInput(graph()->zone(), 2, jsgraph()->UndefinedConstant());
node->InsertInput(graph()->zone(), 3, jsgraph()->UndefinedConstant());
NodeProperties::ChangeOp(node, common()->Call(desc));
return Changed(node);
} else if (p.arity() == 1) {
// TODO(bmeurer): Optimize for the 0 length non-holey case?
ArraySingleArgumentConstructorStub stub(
isolate(), GetHoleyElementsKind(elements_kind), override_mode);
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(), 2,
CallDescriptor::kNeedsFrameState);
node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
node->InsertInput(graph()->zone(), 2, jsgraph()->HeapConstant(site));
node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(1));
node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
NodeProperties::ChangeOp(node, common()->Call(desc));
return Changed(node);
} else {
int const arity = static_cast<int>(p.arity());
ArrayNArgumentsConstructorStub stub(isolate(), elements_kind,
override_mode);
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
isolate(), graph()->zone(), stub.GetCallInterfaceDescriptor(),
arity + 1, CallDescriptor::kNeedsFrameState);
node->ReplaceInput(0, jsgraph()->HeapConstant(stub.GetCode()));
node->InsertInput(graph()->zone(), 2, jsgraph()->UndefinedConstant());
node->InsertInput(graph()->zone(), 3, jsgraph()->Int32Constant(arity));
node->InsertInput(graph()->zone(), 4, jsgraph()->UndefinedConstant());
NodeProperties::ChangeOp(node, common()->Call(desc));
return Changed(node);
}
}
Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) { Reduction JSTypedLowering::ReduceJSCreateClosure(Node* node) {
DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode()); DCHECK_EQ(IrOpcode::kJSCreateClosure, node->opcode());
CreateClosureParameters const& p = CreateClosureParametersOf(node->op()); CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
...@@ -2244,12 +2320,16 @@ Reduction JSTypedLowering::Reduce(Node* node) { ...@@ -2244,12 +2320,16 @@ Reduction JSTypedLowering::Reduce(Node* node) {
return ReduceJSLoadContext(node); return ReduceJSLoadContext(node);
case IrOpcode::kJSStoreContext: case IrOpcode::kJSStoreContext:
return ReduceJSStoreContext(node); return ReduceJSStoreContext(node);
case IrOpcode::kJSLoadNativeContext:
return ReduceJSLoadNativeContext(node);
case IrOpcode::kJSConvertReceiver: case IrOpcode::kJSConvertReceiver:
return ReduceJSConvertReceiver(node); return ReduceJSConvertReceiver(node);
case IrOpcode::kJSCreate: case IrOpcode::kJSCreate:
return ReduceJSCreate(node); return ReduceJSCreate(node);
case IrOpcode::kJSCreateArguments: case IrOpcode::kJSCreateArguments:
return ReduceJSCreateArguments(node); return ReduceJSCreateArguments(node);
case IrOpcode::kJSCreateArray:
return ReduceJSCreateArray(node);
case IrOpcode::kJSCreateClosure: case IrOpcode::kJSCreateClosure:
return ReduceJSCreateClosure(node); return ReduceJSCreateClosure(node);
case IrOpcode::kJSCreateLiteralArray: case IrOpcode::kJSCreateLiteralArray:
......
...@@ -57,6 +57,7 @@ class JSTypedLowering final : public AdvancedReducer { ...@@ -57,6 +57,7 @@ class JSTypedLowering final : public AdvancedReducer {
Reduction ReduceJSInstanceOf(Node* node); Reduction ReduceJSInstanceOf(Node* node);
Reduction ReduceJSLoadContext(Node* node); Reduction ReduceJSLoadContext(Node* node);
Reduction ReduceJSStoreContext(Node* node); Reduction ReduceJSStoreContext(Node* node);
Reduction ReduceJSLoadNativeContext(Node* node);
Reduction ReduceJSEqual(Node* node, bool invert); Reduction ReduceJSEqual(Node* node, bool invert);
Reduction ReduceJSStrictEqual(Node* node, bool invert); Reduction ReduceJSStrictEqual(Node* node, bool invert);
Reduction ReduceJSUnaryNot(Node* node); Reduction ReduceJSUnaryNot(Node* node);
...@@ -69,6 +70,7 @@ class JSTypedLowering final : public AdvancedReducer { ...@@ -69,6 +70,7 @@ class JSTypedLowering final : public AdvancedReducer {
Reduction ReduceJSConvertReceiver(Node* node); Reduction ReduceJSConvertReceiver(Node* node);
Reduction ReduceJSCreate(Node* node); Reduction ReduceJSCreate(Node* node);
Reduction ReduceJSCreateArguments(Node* node); Reduction ReduceJSCreateArguments(Node* node);
Reduction ReduceJSCreateArray(Node* node);
Reduction ReduceJSCreateClosure(Node* node); Reduction ReduceJSCreateClosure(Node* node);
Reduction ReduceJSCreateLiteralArray(Node* node); Reduction ReduceJSCreateLiteralArray(Node* node);
Reduction ReduceJSCreateLiteralObject(Node* node); Reduction ReduceJSCreateLiteralObject(Node* node);
......
...@@ -138,6 +138,17 @@ void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) { ...@@ -138,6 +138,17 @@ void NodeProperties::ReplaceValueInput(Node* node, Node* value, int index) {
} }
// static
void NodeProperties::ReplaceValueInputs(Node* node, Node* value) {
int value_input_count = node->op()->ValueInputCount();
DCHECK_LE(1, value_input_count);
node->ReplaceInput(0, value);
while (--value_input_count > 0) {
node->RemoveInput(value_input_count);
}
}
// static // static
void NodeProperties::ReplaceContextInput(Node* node, Node* context) { void NodeProperties::ReplaceContextInput(Node* node, Node* context) {
node->ReplaceInput(FirstContextIndex(node), context); node->ReplaceInput(FirstContextIndex(node), context);
......
...@@ -88,6 +88,9 @@ class NodeProperties final { ...@@ -88,6 +88,9 @@ class NodeProperties final {
static void RemoveNonValueInputs(Node* node); static void RemoveNonValueInputs(Node* node);
static void RemoveValueInputs(Node* node); static void RemoveValueInputs(Node* node);
// Replaces all value inputs of {node} with the single input {value}.
static void ReplaceValueInputs(Node* node, Node* value);
// Merge the control node {node} into the end of the graph, introducing a // Merge the control node {node} into the end of the graph, introducing a
// merge node or expanding an existing merge node if necessary. // merge node or expanding an existing merge node if necessary.
static void MergeControlToEnd(Graph* graph, CommonOperatorBuilder* common, static void MergeControlToEnd(Graph* graph, CommonOperatorBuilder* common,
......
...@@ -111,6 +111,7 @@ ...@@ -111,6 +111,7 @@
#define JS_OBJECT_OP_LIST(V) \ #define JS_OBJECT_OP_LIST(V) \
V(JSCreate) \ V(JSCreate) \
V(JSCreateArguments) \ V(JSCreateArguments) \
V(JSCreateArray) \
V(JSCreateClosure) \ V(JSCreateClosure) \
V(JSCreateLiteralArray) \ V(JSCreateLiteralArray) \
V(JSCreateLiteralObject) \ V(JSCreateLiteralObject) \
...@@ -128,6 +129,7 @@ ...@@ -128,6 +129,7 @@
V(JSLoadContext) \ V(JSLoadContext) \
V(JSStoreContext) \ V(JSStoreContext) \
V(JSLoadDynamic) \ V(JSLoadDynamic) \
V(JSLoadNativeContext) \
V(JSCreateFunctionContext) \ V(JSCreateFunctionContext) \
V(JSCreateCatchContext) \ V(JSCreateCatchContext) \
V(JSCreateWithContext) \ V(JSCreateWithContext) \
......
...@@ -51,6 +51,7 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) { ...@@ -51,6 +51,7 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
// Object operations // Object operations
case IrOpcode::kJSCreate: case IrOpcode::kJSCreate:
case IrOpcode::kJSCreateArguments: case IrOpcode::kJSCreateArguments:
case IrOpcode::kJSCreateArray:
case IrOpcode::kJSCreateLiteralArray: case IrOpcode::kJSCreateLiteralArray:
case IrOpcode::kJSCreateLiteralObject: case IrOpcode::kJSCreateLiteralObject:
......
...@@ -198,6 +198,12 @@ class PipelineData { ...@@ -198,6 +198,12 @@ class PipelineData {
CommonOperatorBuilder* common() const { return common_; } CommonOperatorBuilder* common() const { return common_; }
JSOperatorBuilder* javascript() const { return javascript_; } JSOperatorBuilder* javascript() const { return javascript_; }
JSGraph* jsgraph() const { return jsgraph_; } JSGraph* jsgraph() const { return jsgraph_; }
MaybeHandle<Context> native_context() const {
if (info()->is_native_context_specializing()) {
return handle(info()->native_context(), isolate());
}
return MaybeHandle<Context>();
}
LoopAssignmentAnalysis* loop_assignment() const { return loop_assignment_; } LoopAssignmentAnalysis* loop_assignment() const { return loop_assignment_; }
void set_loop_assignment(LoopAssignmentAnalysis* loop_assignment) { void set_loop_assignment(LoopAssignmentAnalysis* loop_assignment) {
...@@ -508,7 +514,8 @@ struct InliningPhase { ...@@ -508,7 +514,8 @@ struct InliningPhase {
JSCallReducer call_reducer(data->jsgraph(), JSCallReducer call_reducer(data->jsgraph(),
data->info()->is_deoptimization_enabled() data->info()->is_deoptimization_enabled()
? JSCallReducer::kDeoptimizationEnabled ? JSCallReducer::kDeoptimizationEnabled
: JSCallReducer::kNoFlags); : JSCallReducer::kNoFlags,
data->native_context());
JSContextSpecialization context_specialization( JSContextSpecialization context_specialization(
&graph_reducer, data->jsgraph(), &graph_reducer, data->jsgraph(),
data->info()->is_function_context_specializing() data->info()->is_function_context_specializing()
...@@ -521,19 +528,13 @@ struct InliningPhase { ...@@ -521,19 +528,13 @@ struct InliningPhase {
data->info()->is_deoptimization_enabled() data->info()->is_deoptimization_enabled()
? JSGlobalObjectSpecialization::kDeoptimizationEnabled ? JSGlobalObjectSpecialization::kDeoptimizationEnabled
: JSGlobalObjectSpecialization::kNoFlags, : JSGlobalObjectSpecialization::kNoFlags,
data->info()->is_native_context_specializing() data->native_context(), data->info()->dependencies());
? handle(data->info()->native_context(), data->isolate())
: MaybeHandle<Context>(),
data->info()->dependencies());
JSNativeContextSpecialization native_context_specialization( JSNativeContextSpecialization native_context_specialization(
&graph_reducer, data->jsgraph(), &graph_reducer, data->jsgraph(),
data->info()->is_deoptimization_enabled() data->info()->is_deoptimization_enabled()
? JSNativeContextSpecialization::kDeoptimizationEnabled ? JSNativeContextSpecialization::kDeoptimizationEnabled
: JSNativeContextSpecialization::kNoFlags, : JSNativeContextSpecialization::kNoFlags,
data->info()->is_native_context_specializing() data->native_context(), data->info()->dependencies(), temp_zone);
? handle(data->info()->native_context(), data->isolate())
: MaybeHandle<Context>(),
data->info()->dependencies(), temp_zone);
JSInliningHeuristic inlining(&graph_reducer, JSInliningHeuristic inlining(&graph_reducer,
data->info()->is_inlining_enabled() data->info()->is_inlining_enabled()
? JSInliningHeuristic::kGeneralInlining ? JSInliningHeuristic::kGeneralInlining
......
...@@ -1215,6 +1215,11 @@ Type* Typer::Visitor::TypeJSCreateArguments(Node* node) { ...@@ -1215,6 +1215,11 @@ Type* Typer::Visitor::TypeJSCreateArguments(Node* node) {
} }
Type* Typer::Visitor::TypeJSCreateArray(Node* node) {
return Type::OtherObject();
}
Type* Typer::Visitor::TypeJSCreateClosure(Node* node) { Type* Typer::Visitor::TypeJSCreateClosure(Node* node) {
return Type::OtherObject(); return Type::OtherObject();
} }
...@@ -1380,6 +1385,11 @@ Type* Typer::Visitor::TypeJSStoreContext(Node* node) { ...@@ -1380,6 +1385,11 @@ Type* Typer::Visitor::TypeJSStoreContext(Node* node) {
} }
Type* Typer::Visitor::TypeJSLoadNativeContext(Node* node) {
return Type::Intersect(Type::Internal(), Type::TaggedPointer(), zone());
}
Type* Typer::Visitor::TypeJSLoadDynamic(Node* node) { return Type::Any(); } Type* Typer::Visitor::TypeJSLoadDynamic(Node* node) { return Type::Any(); }
......
...@@ -511,6 +511,10 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -511,6 +511,10 @@ void Verifier::Visitor::Check(Node* node) {
// Type is OtherObject. // Type is OtherObject.
CheckUpperIs(node, Type::OtherObject()); CheckUpperIs(node, Type::OtherObject());
break; break;
case IrOpcode::kJSCreateArray:
// Type is OtherObject.
CheckUpperIs(node, Type::OtherObject());
break;
case IrOpcode::kJSCreateClosure: case IrOpcode::kJSCreateClosure:
// Type is Function. // Type is Function.
CheckUpperIs(node, Type::OtherObject()); CheckUpperIs(node, Type::OtherObject());
...@@ -545,6 +549,7 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -545,6 +549,7 @@ void Verifier::Visitor::Check(Node* node) {
case IrOpcode::kJSLoadContext: case IrOpcode::kJSLoadContext:
case IrOpcode::kJSLoadDynamic: case IrOpcode::kJSLoadDynamic:
case IrOpcode::kJSLoadNativeContext:
// Type can be anything. // Type can be anything.
CheckUpperIs(node, Type::Any()); CheckUpperIs(node, Type::Any());
break; break;
......
...@@ -6258,6 +6258,9 @@ JSObject* JSFunction::global_proxy() { ...@@ -6258,6 +6258,9 @@ JSObject* JSFunction::global_proxy() {
} }
Context* JSFunction::native_context() { return context()->native_context(); }
void JSFunction::set_context(Object* value) { void JSFunction::set_context(Object* value) {
DCHECK(value->IsUndefined() || value->IsContext()); DCHECK(value->IsUndefined() || value->IsContext());
WRITE_FIELD(this, kContextOffset, value); WRITE_FIELD(this, kContextOffset, value);
......
...@@ -7234,6 +7234,7 @@ class JSFunction: public JSObject { ...@@ -7234,6 +7234,7 @@ class JSFunction: public JSObject {
inline Context* context(); inline Context* context();
inline void set_context(Object* context); inline void set_context(Object* context);
inline JSObject* global_proxy(); inline JSObject* global_proxy();
inline Context* native_context();
// [code]: The generated code object for this function. Executed // [code]: The generated code object for this function. Executed
// when the function is invoked, e.g. foo() or new foo(). See // when the function is invoked, e.g. foo() or new foo(). See
......
...@@ -266,6 +266,7 @@ TypeImpl<Config>::BitsetType::Lub(i::Map* map) { ...@@ -266,6 +266,7 @@ TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
// We ought to find a cleaner solution for compiling stubs parameterised // We ought to find a cleaner solution for compiling stubs parameterised
// over type or class variables, esp ones with bounds... // over type or class variables, esp ones with bounds...
return kDetectable & kTaggedPointer; return kDetectable & kTaggedPointer;
case ALLOCATION_SITE_TYPE:
case DECLARED_ACCESSOR_INFO_TYPE: case DECLARED_ACCESSOR_INFO_TYPE:
case EXECUTABLE_ACCESSOR_INFO_TYPE: case EXECUTABLE_ACCESSOR_INFO_TYPE:
case SHARED_FUNCTION_INFO_TYPE: case SHARED_FUNCTION_INFO_TYPE:
...@@ -298,7 +299,6 @@ TypeImpl<Config>::BitsetType::Lub(i::Map* map) { ...@@ -298,7 +299,6 @@ TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
case OBJECT_TEMPLATE_INFO_TYPE: case OBJECT_TEMPLATE_INFO_TYPE:
case SIGNATURE_INFO_TYPE: case SIGNATURE_INFO_TYPE:
case TYPE_SWITCH_INFO_TYPE: case TYPE_SWITCH_INFO_TYPE:
case ALLOCATION_SITE_TYPE:
case ALLOCATION_MEMENTO_TYPE: case ALLOCATION_MEMENTO_TYPE:
case CODE_CACHE_TYPE: case CODE_CACHE_TYPE:
case POLYMORPHIC_CODE_CACHE_TYPE: case POLYMORPHIC_CODE_CACHE_TYPE:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment