From 400b62a1f77164eb5da6aa2171fa4a7b3d72be44 Mon Sep 17 00:00:00 2001 From: "ager@chromium.org" Date: Tue, 26 Jan 2010 13:57:11 +0000 Subject: [PATCH] Implement unary addition in the full (non-optimizing) code generator. Review URL: http://codereview.chromium.org/555099 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3711 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/full-codegen-arm.cc | 13 ++++++++ src/full-codegen.cc | 5 ++- src/ia32/full-codegen-ia32.cc | 13 ++++++++ src/x64/full-codegen-x64.cc | 14 ++++++++ test/mjsunit/compiler/unary-add.js | 67 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 test/mjsunit/compiler/unary-add.js diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index b871e5f..9c178ae 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -1351,6 +1351,19 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } + case Token::ADD: { + Comment cmt(masm_, "[ UnaryOperation (ADD)"); + VisitForValue(expr->expression(), kAccumulator); + Label no_conversion; + __ tst(result_register(), Operand(kSmiTagMask)); + __ b(eq, &no_conversion); + __ push(r0); + __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_JS); + __ bind(&no_conversion); + Apply(context_, result_register()); + break; + } + default: UNREACHABLE(); } diff --git a/src/full-codegen.cc b/src/full-codegen.cc index 25fb0ae..17b9404 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc @@ -418,17 +418,16 @@ void FullCodeGenSyntaxChecker::VisitCallRuntime(CallRuntime* expr) { void FullCodeGenSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) { switch (expr->op()) { - case Token::VOID: + case Token::ADD: case Token::NOT: case Token::TYPEOF: + case Token::VOID: Visit(expr->expression()); break; case Token::BIT_NOT: BAILOUT("UnaryOperation: BIT_NOT"); case Token::DELETE: BAILOUT("UnaryOperation: DELETE"); - case Token::ADD: - BAILOUT("UnaryOperation: ADD"); case Token::SUB: BAILOUT("UnaryOperation: SUB"); default: diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index f7f7984..74de4b9 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -1457,6 +1457,19 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } + case Token::ADD: { + Comment cmt(masm_, "[ UnaryOperation (ADD)"); + VisitForValue(expr->expression(), kAccumulator); + Label no_conversion; + __ test(result_register(), Immediate(kSmiTagMask)); + __ j(zero, &no_conversion); + __ push(result_register()); + __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); + __ bind(&no_conversion); + Apply(context_, result_register()); + break; + } + default: UNREACHABLE(); } diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc index 49f29ce..002840a 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc @@ -1464,6 +1464,20 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { break; } + case Token::ADD: { + Comment cmt(masm_, "[ UnaryOperation (ADD)"); + VisitForValue(expr->expression(), kAccumulator); + Label no_conversion; + Condition is_smi; + is_smi = masm_->CheckSmi(result_register()); + __ j(is_smi, &no_conversion); + __ push(result_register()); + __ InvokeBuiltin(Builtins::TO_NUMBER, CALL_FUNCTION); + __ bind(&no_conversion); + Apply(context_, result_register()); + break; + } + default: UNREACHABLE(); } diff --git a/test/mjsunit/compiler/unary-add.js b/test/mjsunit/compiler/unary-add.js new file mode 100644 index 0000000..b1fc0c2 --- /dev/null +++ b/test/mjsunit/compiler/unary-add.js @@ -0,0 +1,67 @@ +// Copyright 2009 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. + +// Test unary addition in various contexts. + +// Test value context. +assertEquals(1, +'1'); +assertEquals(1, +1); +assertEquals(1.12, +1.12); +assertEquals(NaN, +undefined); +assertEquals(NaN, +{}); + +// Test effect context. +assertEquals(1, eval("+'1'; 1")); +assertEquals(1, eval("+1; 1")); +assertEquals(1, eval("+1.12; 1")); +assertEquals(1, eval("+undefined; 1")); +assertEquals(1, eval("+{}; 1")); + +// Test test context. +assertEquals(1, (+'1') ? 1 : 2); +assertEquals(1, (+1) ? 1 : 2); +assertEquals(1, (+'0') ? 2 : 1); +assertEquals(1, (+0) ? 2 : 1); +assertEquals(1, (+1.12) ? 1 : 2); +assertEquals(1, (+undefined) ? 2 : 1); +assertEquals(1, (+{}) ? 2 : 1); + +// Test value/test context. +assertEquals(1, +'1' || 2); +assertEquals(1, +1 || 2); +assertEquals(1.12, +1.12 || 2); +assertEquals(2, +undefined || 2); +assertEquals(2, +{} || 2); + +// Test test/value context. +assertEquals(2, +'1' && 2); +assertEquals(2, +1 && 2); +assertEquals(0, +'0' && 2); +assertEquals(0, +0 && 2); +assertEquals(2, +1.12 && 2); +assertEquals(NaN, +undefined && 2); +assertEquals(NaN, +{} && 2); -- 2.7.4