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