Reviewers: arv,
Description:
[turbofan] Port initialization of new.target variable.
This implements the proper initialization of the new.target internal
variable in the AstGraphBuilder. For now this uses a runtime call that
cannot handle inlined frames correctly.
[email protected]
Please review this at https://codereview.chromium.org/1212813008/
Base URL: https://chromium.googlesource.com/v8/v8.git@master
Affected files (+60, -17 lines):
M src/compiler/ast-graph-builder.h
M src/compiler/ast-graph-builder.cc
M src/compiler/linkage.cc
M src/frames.h
M src/frames.cc
M src/runtime/runtime.h
M src/runtime/runtime-function.cc
Index: src/compiler/ast-graph-builder.cc
diff --git a/src/compiler/ast-graph-builder.cc
b/src/compiler/ast-graph-builder.cc
index
31cd3fd2d68240571428a7eea72abff45ccfb54a..e802cd8399682122e6fbd1bfc64749f036551bbc
100644
--- a/src/compiler/ast-graph-builder.cc
+++ b/src/compiler/ast-graph-builder.cc
@@ -566,12 +566,11 @@ void AstGraphBuilder::CreateGraphBody(bool
stack_check) {
Variable* rest_parameter = scope->rest_parameter(&rest_index);
BuildRestArgumentsArray(rest_parameter, rest_index);
- // Build .this_function var if it is used.
- BuildThisFunctionVar(scope->this_function_var());
+ // Build assignment to {.this_function} variable if it is used.
+ BuildThisFunctionVariable(scope->this_function_var());
- if (scope->new_target_var() != nullptr) {
- SetStackOverflow();
- }
+ // Build assignment to {new.target} variable if it is used.
+ BuildNewTargetVariable(scope->new_target_var());
// Emit tracing call if requested to do so.
if (FLAG_trace) {
@@ -3144,10 +3143,8 @@ Node*
AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
// This should never lazy deopt, so it is fine to send invalid bailout
id.
FrameStateBeforeAndAfter states(this, BailoutId::None());
- VectorSlotPair feedback;
- BuildVariableAssignment(arguments, object, Token::ASSIGN, feedback,
+ BuildVariableAssignment(arguments, object, Token::ASSIGN,
VectorSlotPair(),
BailoutId::None(), states);
-
return object;
}
@@ -3160,30 +3157,46 @@ Node*
AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
Node* object = NewNode(op, jsgraph()->SmiConstant(index),
jsgraph()->SmiConstant(language_mode()));
- // Assign the object to the rest array
+ // Assign the object to the rest parameter variable.
DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
// This should never lazy deopt, so it is fine to send invalid bailout
id.
FrameStateBeforeAndAfter states(this, BailoutId::None());
- VectorSlotPair feedback;
- BuildVariableAssignment(rest, object, Token::ASSIGN, feedback,
+ BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
BailoutId::None(), states);
-
return object;
}
-Node* AstGraphBuilder::BuildThisFunctionVar(Variable* this_function_var) {
+Node* AstGraphBuilder::BuildThisFunctionVariable(Variable*
this_function_var) {
if (this_function_var == nullptr) return nullptr;
+ // Retrieve the closure we were called with.
Node* this_function = GetFunctionClosure();
+
+ // Assign the object to the {.this_function} variable.
FrameStateBeforeAndAfter states(this, BailoutId::None());
- VectorSlotPair feedback;
BuildVariableAssignment(this_function_var, this_function,
Token::INIT_CONST,
- feedback, BailoutId::None(), states);
+ VectorSlotPair(), BailoutId::None(), states);
return this_function;
}
+Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
+ if (new_target_var == nullptr) return nullptr;
+
+ // Retrieve the original constructor in case we are called as a
constructor.
+ const Operator* op =
+ javascript()->CallRuntime(Runtime::kGetOriginalConstructor, 0);
+ Node* object = NewNode(op);
+
+ // Assign the object to the {new.target} variable.
+ FrameStateBeforeAndAfter states(this, BailoutId::None());
+ BuildVariableAssignment(new_target_var, object, Token::INIT_CONST,
+ VectorSlotPair(), BailoutId::None(), states);
+ return object;
+}
+
+
Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
Node* not_hole) {
Node* the_hole = jsgraph()->TheHoleConstant();
Index: src/compiler/ast-graph-builder.h
diff --git a/src/compiler/ast-graph-builder.h
b/src/compiler/ast-graph-builder.h
index
17190bc8b7adad0612335c14cb2895fa654a5d4f..b2c6f4355d26fa75953ab61c6b46d1abe70bc7a3
100644
--- a/src/compiler/ast-graph-builder.h
+++ b/src/compiler/ast-graph-builder.h
@@ -265,8 +265,11 @@ class AstGraphBuilder : public AstVisitor {
// Builder to create an array of rest parameters if used
Node* BuildRestArgumentsArray(Variable* rest, int index);
- // Builder that assigns to the .this_function internal variable if
needed.
- Node* BuildThisFunctionVar(Variable* this_function_var);
+ // Builder that assigns to the {.this_function} internal variable if
needed.
+ Node* BuildThisFunctionVariable(Variable* this_function_var);
+
+ // Builder that assigns to the {new.target} internal variable if needed.
+ Node* BuildNewTargetVariable(Variable* new_target_var);
// Builders for variable load and assignment.
Node* BuildVariableAssignment(Variable* variable, Node* value,
Index: src/compiler/linkage.cc
diff --git a/src/compiler/linkage.cc b/src/compiler/linkage.cc
index
93bf21a84291918f40b2d63b65f6a52f9aa6e083..6ef014246d95f74dba60a5d0bb079b6a9defdfd8
100644
--- a/src/compiler/linkage.cc
+++ b/src/compiler/linkage.cc
@@ -175,6 +175,7 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId
function) {
case Runtime::kDefineSetterPropertyUnchecked: // TODO(jarin): Is it
safe?
case Runtime::kForInDone:
case Runtime::kForInStep:
+ case Runtime::kGetOriginalConstructor:
case Runtime::kNewArguments:
case Runtime::kNewClosure:
case Runtime::kNewFunctionContext:
Index: src/frames.cc
diff --git a/src/frames.cc b/src/frames.cc
index
cde6f21f74813ddb7f90612293bcc057225929ae..5aefe066f5ba7cfb9f871718525fad9858a88a8d
100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -730,6 +730,17 @@ bool JavaScriptFrame::IsConstructor() const {
}
+Object* JavaScriptFrame::GetOriginalConstructor() const {
+ Address fp = caller_fp();
+ if (has_adapted_arguments()) {
+ // Skip the arguments adaptor frame and look at the real caller.
+ fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
+ }
+ DCHECK(IsConstructFrame(fp));
+ return GetExpression(fp, 2);
+}
+
+
int JavaScriptFrame::GetArgumentsLength() const {
// If there is an arguments adaptor frame get the arguments length from
it.
if (has_adapted_arguments()) {
Index: src/frames.h
diff --git a/src/frames.h b/src/frames.h
index
562445a2f1b115f71ed3ea17f97f0452f90afa03..ca3aba441a284240d44d0ac4796675ab3b257124
100644
--- a/src/frames.h
+++ b/src/frames.h
@@ -533,6 +533,10 @@ class JavaScriptFrame: public StandardFrame {
// Check if this frame is a constructor frame invoked through 'new'.
bool IsConstructor() const;
+ // Returns the original constructor function that was used in the
constructor
+ // call to this frame. Note that this is only valid on constructor
frames.
+ Object* GetOriginalConstructor() const;
+
// Check if this frame has "adapted" arguments in the sense that the
// actual passed arguments are available in an arguments adaptor
// frame below it on the stack.
Index: src/runtime/runtime-function.cc
diff --git a/src/runtime/runtime-function.cc
b/src/runtime/runtime-function.cc
index
d644d37e42b2fff45685eb2c7604c5c68c801a3d..43c9ab4e04f079ebf90eea22f5ee6661eeff3852
100644
--- a/src/runtime/runtime-function.cc
+++ b/src/runtime/runtime-function.cc
@@ -601,6 +601,16 @@ RUNTIME_FUNCTION(Runtime_GetConstructorDelegate) {
}
+RUNTIME_FUNCTION(Runtime_GetOriginalConstructor) {
+ SealHandleScope shs(isolate);
+ DCHECK(args.length() == 0);
+ JavaScriptFrameIterator it(isolate);
+ JavaScriptFrame* frame = it.frame();
+ return frame->IsConstructor() ? frame->GetOriginalConstructor()
+ : isolate->heap()->undefined_value();
+}
+
+
RUNTIME_FUNCTION(Runtime_CallFunction) {
SealHandleScope shs(isolate);
return __RT_impl_Runtime_Call(args, isolate);
Index: src/runtime/runtime.h
diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h
index
37d98603ba21d4b3186a4bc0ab6ed4e6983e74a2..da1ae40ba068cb4c58e7a9ac5595f3dfc2f4e995
100644
--- a/src/runtime/runtime.h
+++ b/src/runtime/runtime.h
@@ -239,6 +239,7 @@ namespace internal {
F(Apply, 5, 1) \
F(GetFunctionDelegate, 1, 1) \
F(GetConstructorDelegate, 1, 1) \
+ F(GetOriginalConstructor, 0, 1) \
F(CallFunction, -1 /* receiver + n args + function */, 1) \
F(IsConstructCall, 0, 1) \
F(IsFunction, 1, 1)
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.