Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Unified Diff: src/ia32/safe-codegen-ia32.cc

Issue 660077: NOT FOR COMMITTING: Add fast side-effect free floating point expressions. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/ia32/safe-codegen-ia32.h ('k') | src/v8-counters.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/safe-codegen-ia32.cc
===================================================================
--- src/ia32/safe-codegen-ia32.cc (revision 0)
+++ src/ia32/safe-codegen-ia32.cc (revision 0)
@@ -0,0 +1,557 @@
+// Copyright 2010 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.
+
+#include "v8.h"
+
+#include "codegen-inl.h"
+#include "compiler.h"
+#include "debug.h"
+#include "ast.h"
+#include "virtual-frame-inl.h"
+#include "safe-codegen-ia32.h"
+#include "parser.h"
+#include "macro-assembler-ia32.h"
+
+namespace v8 {
+namespace internal {
+
+#define __ ACCESS_MASM(masm_)
+
+
+// SafeSyntaxChecker - An AST Visitor that bails out and returns false
+// for any unsupported AST nodes in a side-effect free expression.
+
+#define BAILOUT(reason) \
+ do { \
+ if (FLAG_trace_bailout) { \
+ PrintF("%s\n", reason); \
+ } \
+ has_supported_syntax_ = false; \
+ return; \
+ } while (false)
+
+
+#define CHECK_BAILOUT \
+ do { \
+ if (!has_supported_syntax_) return; \
+ } while (false)
+
+
+#define DEFINE_STMT_VISIT(type) \
+ void SafeSyntaxChecker::Visit##type(type* stmt) { \
+ UNREACHABLE(); \
+ } \
+ \
+ void SafeGenerator::Visit##type(type* stmt) { \
+ UNREACHABLE(); \
+ }
+
+STATEMENT_NODE_LIST(DEFINE_STMT_VISIT)
+
+DEFINE_STMT_VISIT(Declaration)
+
+#undef DEFINE_STMT_VISIT
+
+void SafeSyntaxChecker::VisitFunctionLiteral(FunctionLiteral* expr) {
+ BAILOUT("FunctionLiteral");
+}
+
+
+void SafeSyntaxChecker::VisitFunctionBoilerplateLiteral(
+ FunctionBoilerplateLiteral* expr) {
+ BAILOUT("FunctionBoilerplateLiteral");
+}
+
+
+void SafeSyntaxChecker::VisitConditional(Conditional* expr) {
+ BAILOUT("Conditional");
+}
+
+
+void SafeSyntaxChecker::VisitSlot(Slot* expr) {
+ // Load variables directly from local or parameter slots.
+ // The arguments slot could be the hole, if lazy arguments are used,
+ // and is probably not a smi or heap number in any case.
+ if ((expr->type() == Slot::LOCAL && !expr->is_arguments()) ||
+ expr->type() == Slot::PARAMETER) {
+ ++xmm_stack_height_;
+ if (xmm_stack_height_ > MAX_XMM_STACK_HEIGHT) {
+ BAILOUT("Expression stack overflow");
+ }
+ } else {
+ BAILOUT("Slot is not local or parameter slot.");
+ }
+}
+
+
+void SafeSyntaxChecker::VisitVariableProxy(VariableProxy* expr) {
+ Variable* var = expr->AsVariable();
+ if (var != NULL && var->slot() != NULL) {
+ Visit(var->slot());
+ } else if (var != NULL && var->is_global() && !var->is_this()) {
+ BAILOUT("Global variable");
+ // Global variables are supported. Do nothing.
+ } else {
+ BAILOUT("VariableProxy has non-slot variable");
+ }
+}
+
+
+void SafeSyntaxChecker::VisitLiteral(Literal* expr) {
+ // Check that literal is a number.
+ if (expr->handle()->IsSmi() || expr->handle()->IsHeapNumber()) {
+ ++xmm_stack_height_;
+ if (xmm_stack_height_ > MAX_XMM_STACK_HEIGHT) {
+ BAILOUT("XMM stack height too great");
+ }
+ if (expr->handle()->IsHeapNumber()) {
+ has_constant_float_ = true;
+ }
+ } else {
+ BAILOUT("Non-number literal");
+ }
+}
+
+
+void SafeSyntaxChecker::VisitRegExpLiteral(RegExpLiteral* expr) {
+ BAILOUT("RegExpLiteral");
+}
+
+
+void SafeSyntaxChecker::VisitObjectLiteral(ObjectLiteral* expr) {
+ BAILOUT("ObjectLiteral");
+}
+
+
+void SafeSyntaxChecker::VisitArrayLiteral(ArrayLiteral* expr) {
+ BAILOUT("ArrayLiteral");
+}
+
+
+void SafeSyntaxChecker::VisitCatchExtensionObject(
+ CatchExtensionObject* expr) {
+ BAILOUT("CatchExtensionObject");
+}
+
+
+void SafeSyntaxChecker::VisitAssignment(Assignment* expr) {
+ BAILOUT("Assignment has a side effect");
+}
+
+
+void SafeSyntaxChecker::VisitThrow(Throw* expr) {
+ BAILOUT("Throw");
+}
+
+
+void SafeSyntaxChecker::VisitProperty(Property* expr) {
+ BAILOUT("Property");
+}
+
+
+void SafeSyntaxChecker::VisitCall(Call* expr) {
+ BAILOUT("Call");
+}
+
+
+void SafeSyntaxChecker::VisitCallNew(CallNew* expr) {
+ BAILOUT("CallNew");
+}
+
+
+void SafeSyntaxChecker::VisitCallRuntime(CallRuntime* expr) {
+ BAILOUT("CallRuntime");
+}
+
+
+void SafeSyntaxChecker::VisitUnaryOperation(UnaryOperation* expr) {
+ switch (expr->op()) {
+ case Token::ADD:
+ Visit(expr->expression());
+ break;
+ case Token::SUB:
+ Visit(expr->expression());
+ CHECK_BAILOUT;
+ if (xmm_stack_height_ == MAX_XMM_STACK_HEIGHT) {
+ // Need one extra register for doing the computation.
+ BAILOUT("XMM stack height too great");
+ }
+ ++num_operations_;
+ break;
+ case Token::DELETE:
+ case Token::TYPEOF:
+ case Token::VOID:
+ case Token::BIT_NOT:
+ case Token::NOT:
+ BAILOUT("Unsupported Unary Operation");
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void SafeSyntaxChecker::VisitCountOperation(CountOperation* expr) {
+ BAILOUT("CountOperation");
+}
+
+
+void SafeSyntaxChecker::VisitBinaryOperation(BinaryOperation* expr) {
+ switch (expr->op()) {
+ case Token::ADD:
+ case Token::SUB:
+ case Token::DIV:
+ case Token::MUL:
+ Visit(expr->left());
+ CHECK_BAILOUT;
+ Visit(expr->right());
+ CHECK_BAILOUT;
+ ++num_operations_;
+ --xmm_stack_height_;
+ break;
+ case Token::MOD:
+ case Token::BIT_OR:
+ case Token::BIT_AND:
+ case Token::BIT_XOR:
+ case Token::SHL:
+ case Token::SHR:
+ case Token::SAR:
+ case Token::COMMA:
+ case Token::OR:
+ case Token::AND:
+ BAILOUT("Unsupported Binary Operation");
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void SafeSyntaxChecker::VisitCompareOperation(CompareOperation* expr) {
+ BAILOUT("CompareOperation");
+}
+
+
+void SafeSyntaxChecker::VisitThisFunction(ThisFunction* expr) {
+ BAILOUT("ThisFunction");
+}
+
+
+// Generate code for a side-effect free expression.
+// whesse works above this line
+// --------------------------------------------------
+// lrn works below this line
+
+Result SafeGenerator::Generate(Expression* expr) {
+ JumpTarget allocation_succeeded;
+ Label allocation_failed;
+ ASSERT(CpuFeatures::IsSupported(SSE2));
+ CpuFeatures::Scope fscope(SSE2);
+
+ VirtualFrame* clone = new VirtualFrame(cgen_->frame());
+ __ AllocateHeapNumber(final_result_->reg(), scratch_->reg(),
+ no_reg, &allocation_failed);
+ cgen_->frame()->Push(scratch_);
+ allocation_succeeded.Jump(final_result_);
+ RegisterFile empty_regs;
+ cgen_->SetFrame(clone, &empty_regs);
+ __ bind(&allocation_failed);
+ unsafe_target_->Jump();
+
+ allocation_succeeded.Bind(final_result_);
+ *scratch_ = cgen_->frame()->Pop();
+ Visit(expr);
+ StoreXMM(final_result_->reg());
+ Result return_value = *final_result_;
+ final_result_->Unuse();
+ scratch_->Unuse();
+ return return_value;
+}
+
+void SafeGenerator::PushXMM(Handle<HeapNumber> literal) {
+ XMMRegister reg = AllocateStackElement();
+ __ mov(scratch_->reg(), Immediate(literal));
+ __ movdbl(reg, FieldOperand(scratch_->reg(), HeapNumber::kValueOffset));
+}
+
+
+void SafeGenerator::PushXMM(Handle<Smi> literal) {
+ XMMRegister reg = AllocateStackElement();
+ __ mov(scratch_->reg(), Immediate(literal->value()));
+ __ cvtsi2sd(reg, Operand(scratch_->reg()));
+}
+
+
+void SafeGenerator::PushXMM(Slot* slot) {
+ Register scratch = scratch_->reg();
+ ASSERT((slot->type() == Slot::LOCAL && !slot->is_arguments()) ||
+ slot->type() == Slot::PARAMETER);
+ if (slot->type() == Slot::PARAMETER) {
+ cgen_->frame()->PushParameterAt(slot->index());
+ } else { // slot->type == Slot::LOCAL
+ cgen_->frame()->PushLocalAt(slot->index());
+ }
+ Result value = cgen_->frame()->Pop();
+ XMMRegister reg = AllocateStackElement();
+
+ if (value.is_register()) {
+ // Convert to double.
+ __ test(Operand(value.reg()), Immediate(kSmiTagMask));
+ Label is_smi;
+ Label done;
+ __ j(zero, &is_smi);
+ // This test fails on non-numbers, including the hole representing
+ // an uninitialized constant.
+ __ cmp(FieldOperand(value.reg(), HeapObject::kMapOffset),
+ Immediate(Factory::heap_number_map()));
+ unsafe_target_->Branch(not_equal);
+ __ movdbl(reg, FieldOperand(value.reg(), HeapNumber::kValueOffset));
+ __ jmp(&done);
+
+ __ bind(&is_smi);
+ // Should we spill the existing register, and untag it, or should
+ // we copy to the scratch register?
+ __ mov(scratch, value.reg());
+ __ SmiUntag(scratch);
+ __ cvtsi2sd(reg, Operand(scratch));
+
+ __ bind(&done);
+ } else {
+ ASSERT(value.is_constant());
+ if (value.handle()->IsHeapNumber()) {
+ __ mov(scratch, value.handle());
+ __ movdbl(reg, FieldOperand(scratch, HeapNumber::kValueOffset));
+ } else {
+ ASSERT(value.handle()->IsSmi());
+ __ mov(scratch, Immediate(Smi::cast(*value.handle())->value()));
+ __ cvtsi2sd(reg, Operand(scratch));
+ }
+ }
+}
+
+
+void SafeGenerator::StoreXMM(Register heapNumber) {
+ ASSERT(xmm_stack_height_ > 0);
+ XMMRegister reg = XMMStackElement(0);
+ __ movdbl(FieldOperand(heapNumber, HeapNumber::kValueOffset), reg);
+ FreeStackTop();
+}
+
+
+// Utility functions.
+XMMRegister SafeGenerator::XMMStackElement(int offset_from_top) {
+ ASSERT(offset_from_top < xmm_stack_height_);
+ ASSERT(offset_from_top < kNumXMMRegisters); // The rest have been spilled!
+ int reg_code = (xmm_stack_height_ - offset_from_top - 1);
+ XMMRegister reg = { reg_code };
+ ASSERT(reg.is_valid());
+ return reg;
+}
+
+
+void SafeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitFunctionBoilerplateLiteral(
+ FunctionBoilerplateLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitConditional(Conditional* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitSlot(Slot* expr) {
+ // Check that slot is local or context.
+ if ((expr->type() == Slot::LOCAL && !expr->is_arguments()) ||
+ expr->type() == Slot::PARAMETER) {
+ PushXMM(expr);
+ } else {
+ UNREACHABLE();
+ }
+}
+
+
+void SafeGenerator::VisitVariableProxy(VariableProxy* expr) {
+ Variable* var = expr->AsVariable();
+ if (var != NULL && var->slot() != NULL) {
+ Visit(var->slot());
+ } else {
+ UNREACHABLE();
+ }
+}
+
+
+void SafeGenerator::VisitLiteral(Literal* expr) {
+ // Check that literal is a number.
+ if (expr->handle()->IsSmi()) {
+ PushXMM(Handle<Smi>::cast(expr->handle()));
+ } else if (expr->handle()->IsHeapNumber()) {
+ PushXMM(Handle<HeapNumber>::cast(expr->handle()));
+ } else {
+ UNREACHABLE();
+ }
+}
+
+
+void SafeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitCatchExtensionObject(
+ CatchExtensionObject* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitAssignment(Assignment* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitThrow(Throw* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitProperty(Property* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitCall(Call* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitCallNew(CallNew* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitCallRuntime(CallRuntime* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
+ switch (expr->op()) {
+ case Token::ADD:
+ Visit(expr->expression());
+ break;
+ case Token::SUB: {
+ Visit(expr->expression());
+ XMMRegister arg = XMMStackElement(0);
+ XMMRegister tmp = AllocateStackElement();
+ // Load bit pattern 0x8000000000000000 to new XMM register,
+ // and PXOR it with the result of expr to negate that.
+ __ mov(Operand(scratch_->reg()), Immediate(0x80000000)); // -0 as float.
+ __ movd(tmp, Operand(scratch_->reg()));
+ __ cvtss2sd(tmp, tmp);
+ __ pxor(arg, tmp);
+ FreeStackTop();
+ break;
+ }
+ case Token::DELETE:
+ case Token::TYPEOF:
+ case Token::VOID:
+ case Token::BIT_NOT:
+ case Token::NOT:
+ UNREACHABLE();
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+void SafeGenerator::VisitCountOperation(CountOperation* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitBinaryOperation(BinaryOperation* expr) {
+ Comment cmnt(masm_, "[ BinaryOperation");
+ Visit(expr->left());
+ Visit(expr->right());
+ ASSERT(xmm_stack_height_ >= 2);
+ switch (expr->op()) {
+ case Token::ADD:
+ __ addsd(XMMStackElement(1), XMMStackElement(0));
+ break;
+ case Token::SUB:
+ __ subsd(XMMStackElement(1), XMMStackElement(0));
+ break;
+ case Token::DIV:
+ __ divsd(XMMStackElement(1), XMMStackElement(0));
+ break;
+ case Token::MUL:
+ __ mulsd(XMMStackElement(1), XMMStackElement(0));
+ break;
+ case Token::MOD:
+ case Token::BIT_OR:
+ case Token::BIT_AND:
+ case Token::BIT_XOR:
+ case Token::SHL:
+ case Token::SHR:
+ case Token::SAR:
+ case Token::COMMA:
+ case Token::OR:
+ case Token::AND:
+ default:
+ UNREACHABLE();
+ }
+ FreeStackTop();
+}
+
+
+void SafeGenerator::VisitCompareOperation(CompareOperation* expr) {
+ UNREACHABLE();
+}
+
+
+void SafeGenerator::VisitThisFunction(ThisFunction* expr) {
+ UNREACHABLE();
+}
+#undef __
+
+} } // namespace v8::internal
« no previous file with comments | « src/ia32/safe-codegen-ia32.h ('k') | src/v8-counters.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698