Commit 0ac0e528 authored by ishell's avatar ishell Committed by Commit bot

[turbofan] Fix new.target when a function is inlined to a constructor.

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

Cr-Commit-Position: refs/heads/master@{#31754}
parent 60e8877e
......@@ -3255,6 +3255,7 @@ Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
const Operator* op =
javascript()->CallRuntime(Runtime::kGetOriginalConstructor, 0);
Node* object = NewNode(op);
PrepareFrameState(object, BailoutId::None());
// Assign the object to the {new.target} variable. This should never lazy
// deopt, so it is fine to send invalid bailout id.
......
......@@ -227,7 +227,6 @@ int Linkage::FrameStateInputCount(Runtime::FunctionId function) {
case Runtime::kFinalizeClassDefinition: // TODO(conradw): Is it safe?
case Runtime::kForInDone:
case Runtime::kForInStep:
case Runtime::kGetOriginalConstructor:
case Runtime::kNewClosure:
case Runtime::kNewClosure_Tenured:
case Runtime::kNewFunctionContext:
......
......@@ -749,7 +749,7 @@ bool JavaScriptFrame::IsConstructor() const {
}
bool JavaScriptFrame::HasInlinedFrames() {
bool JavaScriptFrame::HasInlinedFrames() const {
List<JSFunction*> functions(1);
GetFunctions(&functions);
return functions.length() > 1;
......@@ -757,6 +757,7 @@ bool JavaScriptFrame::HasInlinedFrames() {
Object* JavaScriptFrame::GetOriginalConstructor() const {
DCHECK(!HasInlinedFrames());
Address fp = caller_fp();
if (has_adapted_arguments()) {
// Skip the arguments adaptor frame and look at the real caller.
......@@ -799,7 +800,7 @@ Address JavaScriptFrame::GetCallerStackPointer() const {
}
void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) const {
DCHECK(functions->length() == 0);
functions->Add(function());
}
......@@ -1041,7 +1042,7 @@ int OptimizedFrame::LookupExceptionHandlerInTable(
DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
int* deopt_index) {
int* deopt_index) const {
DCHECK(is_optimized());
JSFunction* opt_function = function();
......@@ -1065,7 +1066,7 @@ DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
}
void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) const {
DCHECK(functions->length() == 0);
DCHECK(is_optimized());
......
......@@ -376,18 +376,18 @@ class StackFrame BASE_EMBEDDED {
// Entry frames are used to enter JavaScript execution from C.
class EntryFrame: public StackFrame {
public:
virtual Type type() const { return ENTRY; }
Type type() const override { return ENTRY; }
virtual Code* unchecked_code() const;
Code* unchecked_code() const override;
// Garbage collection support.
virtual void Iterate(ObjectVisitor* v) const;
void Iterate(ObjectVisitor* v) const override;
static EntryFrame* cast(StackFrame* frame) {
DCHECK(frame->is_entry());
return static_cast<EntryFrame*>(frame);
}
virtual void SetCallerFp(Address caller_fp);
void SetCallerFp(Address caller_fp) override;
protected:
inline explicit EntryFrame(StackFrameIteratorBase* iterator);
......@@ -395,11 +395,11 @@ class EntryFrame: public StackFrame {
// The caller stack pointer for entry frames is always zero. The
// real information about the caller frame is available through the
// link to the top exit frame.
virtual Address GetCallerStackPointer() const { return 0; }
Address GetCallerStackPointer() const override { return 0; }
private:
virtual void ComputeCallerState(State* state) const;
virtual Type GetCallerState(State* state) const;
void ComputeCallerState(State* state) const override;
Type GetCallerState(State* state) const override;
friend class StackFrameIteratorBase;
};
......@@ -407,9 +407,9 @@ class EntryFrame: public StackFrame {
class EntryConstructFrame: public EntryFrame {
public:
virtual Type type() const { return ENTRY_CONSTRUCT; }
Type type() const override { return ENTRY_CONSTRUCT; }
virtual Code* unchecked_code() const;
Code* unchecked_code() const override;
static EntryConstructFrame* cast(StackFrame* frame) {
DCHECK(frame->is_entry_construct());
......@@ -427,16 +427,16 @@ class EntryConstructFrame: public EntryFrame {
// Exit frames are used to exit JavaScript execution and go to C.
class ExitFrame: public StackFrame {
public:
virtual Type type() const { return EXIT; }
Type type() const override { return EXIT; }
virtual Code* unchecked_code() const;
Code* unchecked_code() const override;
Object*& code_slot() const;
// Garbage collection support.
virtual void Iterate(ObjectVisitor* v) const;
void Iterate(ObjectVisitor* v) const override;
virtual void SetCallerFp(Address caller_fp);
void SetCallerFp(Address caller_fp) override;
static ExitFrame* cast(StackFrame* frame) {
DCHECK(frame->is_exit());
......@@ -453,10 +453,10 @@ class ExitFrame: public StackFrame {
protected:
inline explicit ExitFrame(StackFrameIteratorBase* iterator);
virtual Address GetCallerStackPointer() const;
Address GetCallerStackPointer() const override;
private:
virtual void ComputeCallerState(State* state) const;
void ComputeCallerState(State* state) const override;
friend class StackFrameIteratorBase;
};
......@@ -465,7 +465,7 @@ class ExitFrame: public StackFrame {
class StandardFrame: public StackFrame {
public:
// Testers.
virtual bool is_standard() const { return true; }
bool is_standard() const override { return true; }
// Accessors.
inline Object* context() const;
......@@ -476,7 +476,7 @@ class StandardFrame: public StackFrame {
int ComputeExpressionsCount() const;
static Object* GetExpression(Address fp, int index);
virtual void SetCallerFp(Address caller_fp);
void SetCallerFp(Address caller_fp) override;
static StandardFrame* cast(StackFrame* frame) {
DCHECK(frame->is_standard());
......@@ -486,7 +486,7 @@ class StandardFrame: public StackFrame {
protected:
inline explicit StandardFrame(StackFrameIteratorBase* iterator);
virtual void ComputeCallerState(State* state) const;
void ComputeCallerState(State* state) const override;
// Accessors.
inline Address caller_fp() const;
......@@ -550,7 +550,7 @@ class FrameSummary BASE_EMBEDDED {
class JavaScriptFrame: public StandardFrame {
public:
virtual Type type() const { return JAVA_SCRIPT; }
Type type() const override { return JAVA_SCRIPT; }
// Accessors.
inline JSFunction* function() const;
......@@ -581,7 +581,7 @@ class JavaScriptFrame: public StandardFrame {
// Determines whether this frame includes inlined activations. To get details
// about the inlined frames use {GetFunctions} and {Summarize}.
bool HasInlinedFrames();
bool HasInlinedFrames() 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.
......@@ -594,18 +594,17 @@ class JavaScriptFrame: public StandardFrame {
int GetArgumentsLength() const;
// Garbage collection support.
virtual void Iterate(ObjectVisitor* v) const;
void Iterate(ObjectVisitor* v) const override;
// Printing support.
virtual void Print(StringStream* accumulator,
PrintMode mode,
int index) const;
void Print(StringStream* accumulator, PrintMode mode,
int index) const override;
// Determine the code for the frame.
virtual Code* unchecked_code() const;
Code* unchecked_code() const override;
// Return a list with JSFunctions of this frame.
virtual void GetFunctions(List<JSFunction*>* functions);
virtual void GetFunctions(List<JSFunction*>* functions) const;
// Build a list with summaries for this frame including all inlined frames.
virtual void Summarize(List<FrameSummary>* frames);
......@@ -635,7 +634,7 @@ class JavaScriptFrame: public StandardFrame {
protected:
inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
virtual Address GetCallerStackPointer() const;
Address GetCallerStackPointer() const override;
virtual int GetNumberOfIncomingArguments() const;
......@@ -652,18 +651,18 @@ class JavaScriptFrame: public StandardFrame {
class StubFrame : public StandardFrame {
public:
virtual Type type() const { return STUB; }
Type type() const override { return STUB; }
// GC support.
virtual void Iterate(ObjectVisitor* v) const;
void Iterate(ObjectVisitor* v) const override;
// Determine the code for the frame.
virtual Code* unchecked_code() const;
Code* unchecked_code() const override;
protected:
inline explicit StubFrame(StackFrameIteratorBase* iterator);
virtual Address GetCallerStackPointer() const;
Address GetCallerStackPointer() const override;
virtual int GetNumberOfIncomingArguments() const;
......@@ -673,24 +672,24 @@ class StubFrame : public StandardFrame {
class OptimizedFrame : public JavaScriptFrame {
public:
virtual Type type() const { return OPTIMIZED; }
Type type() const override { return OPTIMIZED; }
// GC support.
virtual void Iterate(ObjectVisitor* v) const;
void Iterate(ObjectVisitor* v) const override;
// Return a list with JSFunctions of this frame.
// The functions are ordered bottom-to-top (i.e. functions.last()
// is the top-most activation)
virtual void GetFunctions(List<JSFunction*>* functions);
void GetFunctions(List<JSFunction*>* functions) const override;
virtual void Summarize(List<FrameSummary>* frames);
void Summarize(List<FrameSummary>* frames) override;
// Lookup exception handler for current {pc}, returns -1 if none found. Also
// returns the expected number of stack slots at the handler site.
virtual int LookupExceptionHandlerInTable(
int* stack_slots, HandlerTable::CatchPrediction* prediction);
int LookupExceptionHandlerInTable(
int* stack_slots, HandlerTable::CatchPrediction* prediction) override;
DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
DeoptimizationInputData* GetDeoptimizationData(int* deopt_index) const;
static int StackSlotOffsetRelativeToFp(int slot_index);
......@@ -705,7 +704,7 @@ class OptimizedFrame : public JavaScriptFrame {
class InterpretedFrame : public JavaScriptFrame {
virtual Type type() const { return INTERPRETED; }
Type type() const override { return INTERPRETED; }
protected:
inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
......@@ -720,10 +719,10 @@ class InterpretedFrame : public JavaScriptFrame {
// match the formal number of parameters.
class ArgumentsAdaptorFrame: public JavaScriptFrame {
public:
virtual Type type() const { return ARGUMENTS_ADAPTOR; }
Type type() const override { return ARGUMENTS_ADAPTOR; }
// Determine the code for the frame.
virtual Code* unchecked_code() const;
Code* unchecked_code() const override;
static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
DCHECK(frame->is_arguments_adaptor());
......@@ -731,16 +730,15 @@ class ArgumentsAdaptorFrame: public JavaScriptFrame {
}
// Printing support.
virtual void Print(StringStream* accumulator,
PrintMode mode,
int index) const;
void Print(StringStream* accumulator, PrintMode mode,
int index) const override;
protected:
inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
virtual int GetNumberOfIncomingArguments() const;
int GetNumberOfIncomingArguments() const override;
virtual Address GetCallerStackPointer() const;
Address GetCallerStackPointer() const override;
private:
friend class StackFrameIteratorBase;
......@@ -749,13 +747,13 @@ class ArgumentsAdaptorFrame: public JavaScriptFrame {
class InternalFrame: public StandardFrame {
public:
virtual Type type() const { return INTERNAL; }
Type type() const override { return INTERNAL; }
// Garbage collection support.
virtual void Iterate(ObjectVisitor* v) const;
void Iterate(ObjectVisitor* v) const override;
// Determine the code for the frame.
virtual Code* unchecked_code() const;
Code* unchecked_code() const override;
static InternalFrame* cast(StackFrame* frame) {
DCHECK(frame->is_internal());
......@@ -765,7 +763,7 @@ class InternalFrame: public StandardFrame {
protected:
inline explicit InternalFrame(StackFrameIteratorBase* iterator);
virtual Address GetCallerStackPointer() const;
Address GetCallerStackPointer() const override;
private:
friend class StackFrameIteratorBase;
......@@ -782,13 +780,13 @@ class StubFailureTrampolineFrame: public StandardFrame {
static const int kCallerStackParameterCountFrameOffset =
StandardFrameConstants::kMarkerOffset - 2 * kPointerSize;
virtual Type type() const { return STUB_FAILURE_TRAMPOLINE; }
Type type() const override { return STUB_FAILURE_TRAMPOLINE; }
// Get the code associated with this frame.
// This method could be called during marking phase of GC.
virtual Code* unchecked_code() const;
Code* unchecked_code() const override;
virtual void Iterate(ObjectVisitor* v) const;
void Iterate(ObjectVisitor* v) const override;
// Architecture-specific register description.
static Register fp_register();
......@@ -799,7 +797,7 @@ class StubFailureTrampolineFrame: public StandardFrame {
inline explicit StubFailureTrampolineFrame(
StackFrameIteratorBase* iterator);
virtual Address GetCallerStackPointer() const;
Address GetCallerStackPointer() const override;
private:
friend class StackFrameIteratorBase;
......@@ -810,7 +808,7 @@ class StubFailureTrampolineFrame: public StandardFrame {
// function invocations through 'new'.
class ConstructFrame: public InternalFrame {
public:
virtual Type type() const { return CONSTRUCT; }
Type type() const override { return CONSTRUCT; }
static ConstructFrame* cast(StackFrame* frame) {
DCHECK(frame->is_construct());
......
......@@ -542,8 +542,10 @@ RUNTIME_FUNCTION(Runtime_GetOriginalConstructor) {
DCHECK(args.length() == 0);
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
return frame->IsConstructor() ? frame->GetOriginalConstructor()
: isolate->heap()->undefined_value();
// Currently we don't inline [[Construct]] calls.
return frame->IsConstructor() && !frame->HasInlinedFrames()
? frame->GetOriginalConstructor()
: isolate->heap()->undefined_value();
}
......
......@@ -385,6 +385,23 @@
})();
// Has to be top-level to be inlined.
function get_new_target() { return new.target; }
(function TestInlining() {
"use strict";
new function() { assertEquals(undefined, get_new_target()); }
new function() { assertEquals(get_new_target, new get_new_target()); }
class A extends get_new_target {
constructor() {
var new_target = super();
this.new_target = new_target;
}
}
assertEquals(A, new A().new_target);
})();
(function TestEarlyErrors() {
assertThrows(function() { Function("new.target = 42"); }, ReferenceError);
assertThrows(function() { Function("var foo = 1; new.target = foo = 42"); }, ReferenceError);
......
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