diff --git a/src/a64/lithium-codegen-a64.cc b/src/a64/lithium-codegen-a64.cc index fea4db7ffd..0148349a14 100644 --- a/src/a64/lithium-codegen-a64.cc +++ b/src/a64/lithium-codegen-a64.cc @@ -342,10 +342,6 @@ void LCodeGen::AddToTranslation(LEnvironment* environment, } } else if (op->IsDoubleStackSlot()) { translation->StoreDoubleStackSlot(op->index()); - } else if (op->IsArgument()) { - ASSERT(is_tagged); - int src_index = GetStackSlotCount() + op->index(); - translation->StoreStackSlot(src_index); } else if (op->IsRegister()) { Register reg = ToRegister(op); if (is_tagged) { diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 6269a7abd4..dd012af579 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -427,7 +427,7 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { __ Move(scratch, literal); } return scratch; - } else if (op->IsStackSlot() || op->IsArgument()) { + } else if (op->IsStackSlot()) { __ ldr(scratch, ToMemOperand(op)); return scratch; } @@ -463,7 +463,7 @@ DwVfpRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, } else if (r.IsTagged()) { Abort(kUnsupportedTaggedImmediate); } - } else if (op->IsStackSlot() || op->IsArgument()) { + } else if (op->IsStackSlot()) { // TODO(regis): Why is vldr not taking a MemOperand? // __ vldr(dbl_scratch, ToMemOperand(op)); MemOperand mem_op = ToMemOperand(op); @@ -683,10 +683,6 @@ void LCodeGen::AddToTranslation(LEnvironment* environment, } } else if (op->IsDoubleStackSlot()) { translation->StoreDoubleStackSlot(op->index()); - } else if (op->IsArgument()) { - ASSERT(is_tagged); - int src_index = GetStackSlotCount() + op->index(); - translation->StoreStackSlot(src_index); } else if (op->IsRegister()) { Register reg = ToRegister(op); if (is_tagged) { @@ -1669,7 +1665,7 @@ void LCodeGen::DoBitI(LBitI* instr) { Register result = ToRegister(instr->result()); Operand right(no_reg); - if (right_op->IsStackSlot() || right_op->IsArgument()) { + if (right_op->IsStackSlot()) { right = Operand(EmitLoadRegister(right_op, ip)); } else { ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); @@ -1792,7 +1788,7 @@ void LCodeGen::DoSubI(LSubI* instr) { bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); SBit set_cond = can_overflow ? SetCC : LeaveCC; - if (right->IsStackSlot() || right->IsArgument()) { + if (right->IsStackSlot()) { Register right_reg = EmitLoadRegister(right, ip); __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); } else { @@ -1813,7 +1809,7 @@ void LCodeGen::DoRSubI(LRSubI* instr) { bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); SBit set_cond = can_overflow ? SetCC : LeaveCC; - if (right->IsStackSlot() || right->IsArgument()) { + if (right->IsStackSlot()) { Register right_reg = EmitLoadRegister(right, ip); __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); } else { @@ -1986,7 +1982,7 @@ void LCodeGen::DoAddI(LAddI* instr) { bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); SBit set_cond = can_overflow ? SetCC : LeaveCC; - if (right->IsStackSlot() || right->IsArgument()) { + if (right->IsStackSlot()) { Register right_reg = EmitLoadRegister(right, ip); __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); } else { diff --git a/src/hydrogen.cc b/src/hydrogen.cc index 55d19e05b2..891b58facd 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -3892,7 +3892,6 @@ void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) { } - void HOptimizedGraphBuilder::VisitForControl(Expression* expr, HBasicBlock* true_block, HBasicBlock* false_block) { @@ -3901,20 +3900,6 @@ void HOptimizedGraphBuilder::VisitForControl(Expression* expr, } -void HOptimizedGraphBuilder::VisitArgument(Expression* expr) { - CHECK_ALIVE(VisitForValue(expr)); - Push(Add(Pop())); -} - - -void HOptimizedGraphBuilder::VisitArgumentList( - ZoneList* arguments) { - for (int i = 0; i < arguments->length(); i++) { - CHECK_ALIVE(VisitArgument(arguments->at(i))); - } -} - - void HOptimizedGraphBuilder::VisitExpressions( ZoneList* exprs) { for (int i = 0; i < exprs->length(); ++i) { @@ -8055,6 +8040,10 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { return Bailout(kPossibleDirectCallToEval); } + // The function is on the stack in the unoptimized code during + // evaluation of the arguments. + CHECK_ALIVE(VisitForValue(expr->expression())); + HValue* function = Top(); bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); if (global_call) { Variable* var = proxy->var(); @@ -8069,8 +8058,6 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { Handle global(current_info()->global_object()); known_global_function = expr->ComputeGlobalTarget(global, &lookup); } - CHECK_ALIVE(VisitForValue(expr->expression())); - HValue* function = Top(); if (known_global_function) { Add(function, expr->target()); @@ -8097,18 +8084,13 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { PushArgumentsFromEnvironment(argument_count); call = BuildCallConstantFunction(expr->target(), argument_count); } else { - Push(Add(graph()->GetConstantUndefined())); - CHECK_ALIVE(VisitArgumentList(expr->arguments())); + Push(graph()->GetConstantUndefined()); + CHECK_ALIVE(VisitExpressions(expr->arguments())); + PushArgumentsFromEnvironment(argument_count); call = New(function, argument_count); - Drop(argument_count); } } else if (expr->IsMonomorphic()) { - // The function is on the stack in the unoptimized code during - // evaluation of the arguments. - CHECK_ALIVE(VisitForValue(expr->expression())); - HValue* function = Top(); - Add(function, expr->target()); Push(graph()->GetConstantUndefined()); @@ -8134,13 +8116,10 @@ void HOptimizedGraphBuilder::VisitCall(Call* expr) { function, expr->target(), argument_count)); } else { - CHECK_ALIVE(VisitForValue(expr->expression())); - HValue* function = Top(); - HValue* receiver = graph()->GetConstantUndefined(); - Push(Add(receiver)); - CHECK_ALIVE(VisitArgumentList(expr->arguments())); + Push(graph()->GetConstantUndefined()); + CHECK_ALIVE(VisitExpressions(expr->arguments())); + PushArgumentsFromEnvironment(argument_count); call = New(function, argument_count); - Drop(argument_count); } } @@ -8580,13 +8559,13 @@ void HOptimizedGraphBuilder::VisitTypedArrayInitialize( if (!is_zero_byte_offset) { byte_offset_smi.Else(); { // byte_offset is not Smi. - Push(Add(obj)); - VisitArgument(arguments->at(kArrayIdArg)); - Push(Add(buffer)); - Push(Add(byte_offset)); - Push(Add(byte_length)); + Push(obj); + CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg))); + Push(buffer); + Push(byte_offset); + Push(byte_length); + PushArgumentsFromEnvironment(kArgsLength); Add(expr->name(), expr->function(), kArgsLength); - Drop(kArgsLength); } } byte_offset_smi.End(); @@ -8633,13 +8612,12 @@ void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) { (this->*generator)(expr); } else { ASSERT(function->intrinsic_type == Runtime::RUNTIME); - CHECK_ALIVE(VisitArgumentList(expr->arguments())); - Handle name = expr->name(); int argument_count = expr->arguments()->length(); + CHECK_ALIVE(VisitExpressions(expr->arguments())); + PushArgumentsFromEnvironment(argument_count); HCallRuntime* call = New(name, function, argument_count); - Drop(argument_count); return ast_context()->ReturnInstruction(call, expr->id()); } } @@ -10504,9 +10482,9 @@ void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { // Fast support for SubString. void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { ASSERT_EQ(3, call->arguments()->length()); - CHECK_ALIVE(VisitArgumentList(call->arguments())); + CHECK_ALIVE(VisitExpressions(call->arguments())); + PushArgumentsFromEnvironment(call->arguments()->length()); HCallStub* result = New(CodeStub::SubString, 3); - Drop(3); return ast_context()->ReturnInstruction(result, call->id()); } @@ -10514,9 +10492,9 @@ void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { // Fast support for StringCompare. void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { ASSERT_EQ(2, call->arguments()->length()); - CHECK_ALIVE(VisitArgumentList(call->arguments())); + CHECK_ALIVE(VisitExpressions(call->arguments())); + PushArgumentsFromEnvironment(call->arguments()->length()); HCallStub* result = New(CodeStub::StringCompare, 2); - Drop(2); return ast_context()->ReturnInstruction(result, call->id()); } @@ -10524,9 +10502,9 @@ void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) { // Support for direct calls from JavaScript to native RegExp code. void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) { ASSERT_EQ(4, call->arguments()->length()); - CHECK_ALIVE(VisitArgumentList(call->arguments())); + CHECK_ALIVE(VisitExpressions(call->arguments())); + PushArgumentsFromEnvironment(call->arguments()->length()); HCallStub* result = New(CodeStub::RegExpExec, 4); - Drop(4); return ast_context()->ReturnInstruction(result, call->id()); } @@ -10567,12 +10545,11 @@ void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { int arg_count = call->arguments()->length() - 1; ASSERT(arg_count >= 1); // There's always at least a receiver. - for (int i = 0; i < arg_count; ++i) { - CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); - } - CHECK_ALIVE(VisitForValue(call->arguments()->last())); - + CHECK_ALIVE(VisitExpressions(call->arguments())); + // The function is the last argument HValue* function = Pop(); + // Push the arguments to the stack + PushArgumentsFromEnvironment(arg_count); IfBuilder if_is_jsfunction(this); if_is_jsfunction.If(function, JS_FUNCTION_TYPE); @@ -10581,7 +10558,6 @@ void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { { HInstruction* invoke_result = Add(function, arg_count); - Drop(arg_count); if (!ast_context()->IsEffect()) { Push(invoke_result); } @@ -10592,7 +10568,6 @@ void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { { HInstruction* call_result = Add(function, arg_count); - Drop(arg_count); if (!ast_context()->IsEffect()) { Push(call_result); } diff --git a/src/hydrogen.h b/src/hydrogen.h index b9d53be94e..cab7163548 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -2214,11 +2214,6 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { HBasicBlock* true_block, HBasicBlock* false_block); - // Visit an argument subexpression and emit a push to the outgoing arguments. - void VisitArgument(Expression* expr); - - void VisitArgumentList(ZoneList* arguments); - // Visit a list of expressions from left to right, each in a value context. void VisitExpressions(ZoneList* exprs); diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index be7dc44f48..3e8224b24f 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -952,10 +952,6 @@ void LCodeGen::AddToTranslation(LEnvironment* environment, } } else if (op->IsDoubleStackSlot()) { translation->StoreDoubleStackSlot(op->index()); - } else if (op->IsArgument()) { - ASSERT(is_tagged); - int src_index = GetStackSlotCount() + op->index(); - translation->StoreStackSlot(src_index); } else if (op->IsRegister()) { Register reg = ToRegister(op); if (is_tagged) { diff --git a/src/lithium-allocator.h b/src/lithium-allocator.h index 9908ea823d..d5d871e439 100644 --- a/src/lithium-allocator.h +++ b/src/lithium-allocator.h @@ -47,7 +47,6 @@ class HValue; class BitVector; class StringStream; -class LArgument; class LPlatformChunk; class LOperand; class LUnallocated; diff --git a/src/lithium.cc b/src/lithium.cc index ab1e630c70..d3b49b51d3 100644 --- a/src/lithium.cc +++ b/src/lithium.cc @@ -111,9 +111,6 @@ void LOperand::PrintTo(StringStream* stream) { case DOUBLE_REGISTER: stream->Add("[%s|R]", DoubleRegister::AllocationIndexToString(index())); break; - case ARGUMENT: - stream->Add("[arg:%d]", index()); - break; } } @@ -498,10 +495,9 @@ LEnvironment* LChunkBuilderBase::CreateEnvironment( LOperand* op; HValue* value = hydrogen_env->values()->at(i); + CHECK(!value->IsPushArgument()); // Do not deopt outgoing arguments if (value->IsArgumentsObject() || value->IsCapturedObject()) { op = LEnvironment::materialization_marker(); - } else if (value->IsPushArgument()) { - op = new(zone()) LArgument(argument_index++); } else { op = UseAny(value); } diff --git a/src/lithium.h b/src/lithium.h index 754f88da82..439479cb41 100644 --- a/src/lithium.h +++ b/src/lithium.h @@ -52,8 +52,7 @@ class LOperand : public ZoneObject { STACK_SLOT, DOUBLE_STACK_SLOT, REGISTER, - DOUBLE_REGISTER, - ARGUMENT + DOUBLE_REGISTER }; LOperand() : value_(KindField::encode(INVALID)) { } @@ -63,7 +62,6 @@ class LOperand : public ZoneObject { #define LITHIUM_OPERAND_PREDICATE(name, type) \ bool Is##name() const { return kind() == type; } LITHIUM_OPERAND_LIST(LITHIUM_OPERAND_PREDICATE) - LITHIUM_OPERAND_PREDICATE(Argument, ARGUMENT) LITHIUM_OPERAND_PREDICATE(Unallocated, UNALLOCATED) LITHIUM_OPERAND_PREDICATE(Ignored, INVALID) #undef LITHIUM_OPERAND_PREDICATE @@ -342,17 +340,6 @@ class LConstantOperand V8_FINAL : public LOperand { }; -class LArgument V8_FINAL : public LOperand { - public: - explicit LArgument(int index) : LOperand(ARGUMENT, index) { } - - static LArgument* cast(LOperand* op) { - ASSERT(op->IsArgument()); - return reinterpret_cast(op); - } -}; - - class LStackSlot V8_FINAL : public LOperand { public: static LStackSlot* Create(int index, Zone* zone) { @@ -679,7 +666,7 @@ class ShallowIterator V8_FINAL BASE_EMBEDDED { private: bool ShouldSkip(LOperand* op) { - return op == NULL || op->IsConstantOperand() || op->IsArgument(); + return op == NULL || op->IsConstantOperand(); } // Skip until something interesting, beginning with and including current_. diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc index 834c5d5504..b9607dea7d 100644 --- a/src/mips/lithium-codegen-mips.cc +++ b/src/mips/lithium-codegen-mips.cc @@ -401,7 +401,7 @@ Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { __ li(scratch, literal); } return scratch; - } else if (op->IsStackSlot() || op->IsArgument()) { + } else if (op->IsStackSlot()) { __ lw(scratch, ToMemOperand(op)); return scratch; } @@ -437,7 +437,7 @@ DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, } else if (r.IsTagged()) { Abort(kUnsupportedTaggedImmediate); } - } else if (op->IsStackSlot() || op->IsArgument()) { + } else if (op->IsStackSlot()) { MemOperand mem_op = ToMemOperand(op); __ ldc1(dbl_scratch, mem_op); return dbl_scratch; @@ -655,10 +655,6 @@ void LCodeGen::AddToTranslation(LEnvironment* environment, } } else if (op->IsDoubleStackSlot()) { translation->StoreDoubleStackSlot(op->index()); - } else if (op->IsArgument()) { - ASSERT(is_tagged); - int src_index = GetStackSlotCount() + op->index(); - translation->StoreStackSlot(src_index); } else if (op->IsRegister()) { Register reg = ToRegister(op); if (is_tagged) { @@ -1467,7 +1463,7 @@ void LCodeGen::DoBitI(LBitI* instr) { Register result = ToRegister(instr->result()); Operand right(no_reg); - if (right_op->IsStackSlot() || right_op->IsArgument()) { + if (right_op->IsStackSlot()) { right = Operand(EmitLoadRegister(right_op, at)); } else { ASSERT(right_op->IsRegister() || right_op->IsConstantOperand()); @@ -1589,7 +1585,7 @@ void LCodeGen::DoSubI(LSubI* instr) { bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); if (!can_overflow) { - if (right->IsStackSlot() || right->IsArgument()) { + if (right->IsStackSlot()) { Register right_reg = EmitLoadRegister(right, at); __ Subu(ToRegister(result), ToRegister(left), Operand(right_reg)); } else { @@ -1599,9 +1595,7 @@ void LCodeGen::DoSubI(LSubI* instr) { } else { // can_overflow. Register overflow = scratch0(); Register scratch = scratch1(); - if (right->IsStackSlot() || - right->IsArgument() || - right->IsConstantOperand()) { + if (right->IsStackSlot() || right->IsConstantOperand()) { Register right_reg = EmitLoadRegister(right, scratch); __ SubuAndCheckForOverflow(ToRegister(result), ToRegister(left), @@ -1781,7 +1775,7 @@ void LCodeGen::DoAddI(LAddI* instr) { bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); if (!can_overflow) { - if (right->IsStackSlot() || right->IsArgument()) { + if (right->IsStackSlot()) { Register right_reg = EmitLoadRegister(right, at); __ Addu(ToRegister(result), ToRegister(left), Operand(right_reg)); } else { @@ -1792,7 +1786,6 @@ void LCodeGen::DoAddI(LAddI* instr) { Register overflow = scratch0(); Register scratch = scratch1(); if (right->IsStackSlot() || - right->IsArgument() || right->IsConstantOperand()) { Register right_reg = EmitLoadRegister(right, scratch); __ AdduAndCheckForOverflow(ToRegister(result), diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index e513e14bff..36ebcad53c 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -571,10 +571,6 @@ void LCodeGen::AddToTranslation(LEnvironment* environment, } } else if (op->IsDoubleStackSlot()) { translation->StoreDoubleStackSlot(op->index()); - } else if (op->IsArgument()) { - ASSERT(is_tagged); - int src_index = GetStackSlotCount() + op->index(); - translation->StoreStackSlot(src_index); } else if (op->IsRegister()) { Register reg = ToRegister(op); if (is_tagged) { diff --git a/test/mjsunit/regress/regress-3183.js b/test/mjsunit/regress/regress-3183.js new file mode 100644 index 0000000000..0c915b0aec --- /dev/null +++ b/test/mjsunit/regress/regress-3183.js @@ -0,0 +1,96 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax + +(function DeoptimizeArgCallFunctionGeneric() { + var a = []; + + function f1(method, array, elem, deopt) { + assertEquals('push', method); + } + + function f2() { } + + function bar(x, deopt, f) { + f('push', a, [x], deopt + 0); + } + + function foo() { return bar(arguments[0], arguments[1], arguments[2]); } + function baz(f, deopt) { return foo("x", deopt, f); } + + baz(f1, 0); + baz(f2, 0); + %OptimizeFunctionOnNextCall(baz); + baz(f1, "deopt"); +})(); + + +(function DeoptimizeArgGlobalFunctionGeneric() { + var a = []; + + var f1; + + f1 = function(method, array, elem, deopt) { + assertEquals('push', method); + } + + function bar(x, deopt, f) { + f1('push', a, [x], deopt + 0); + } + + function foo() { return bar(arguments[0], arguments[1]); } + function baz(deopt) { return foo("x", deopt); } + + baz(0); + baz(0); + %OptimizeFunctionOnNextCall(baz); + baz("deopt"); +})(); + + +(function DeoptimizeArgCallFunctionRuntime() { + var a = []; + + var f1; + + f1 = function(method, array, elem, deopt) { + assertEquals('push', method); + } + + function bar(x, deopt) { + %_CallFunction(null, 'push', [x][0], ((deopt + 0), 1), f1); + } + + function foo() { return bar(arguments[0], arguments[1]); } + function baz(deopt) { return foo(0, deopt); } + + baz(0); + baz(0); + %OptimizeFunctionOnNextCall(baz); + baz("deopt"); +})();