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

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

Issue 545007: Introduce number type information in the virtual frame. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: merged with latest rev. 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/codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ia32/codegen-ia32.cc
===================================================================
--- src/ia32/codegen-ia32.cc (revision 3859)
+++ src/ia32/codegen-ia32.cc (working copy)
@@ -722,35 +722,54 @@
// The value to convert should be popped from the frame.
Result value = frame_->Pop();
value.ToRegister();
- // Fast case checks.
- // 'false' => false.
- __ cmp(value.reg(), Factory::false_value());
- dest->false_target()->Branch(equal);
+ if (value.is_number()) {
+ Comment cmnt(masm_, "ONLY_NUMBER");
+ // Fast case if NumberInfo indicates only numbers.
+ if (FLAG_debug_code) {
+ __ AbortIfNotNumber(value.reg(), "ToBoolean operand is not a number.");
+ }
+ // Smi => false iff zero.
+ ASSERT(kSmiTag == 0);
+ __ test(value.reg(), Operand(value.reg()));
+ dest->false_target()->Branch(zero);
+ __ test(value.reg(), Immediate(kSmiTagMask));
+ dest->true_target()->Branch(zero);
+ __ fldz();
+ __ fld_d(FieldOperand(value.reg(), HeapNumber::kValueOffset));
+ __ FCmp();
+ value.Unuse();
+ dest->Split(not_zero);
+ } else {
+ // Fast case checks.
+ // 'false' => false.
+ __ cmp(value.reg(), Factory::false_value());
+ dest->false_target()->Branch(equal);
- // 'true' => true.
- __ cmp(value.reg(), Factory::true_value());
- dest->true_target()->Branch(equal);
+ // 'true' => true.
+ __ cmp(value.reg(), Factory::true_value());
+ dest->true_target()->Branch(equal);
- // 'undefined' => false.
- __ cmp(value.reg(), Factory::undefined_value());
- dest->false_target()->Branch(equal);
+ // 'undefined' => false.
+ __ cmp(value.reg(), Factory::undefined_value());
+ dest->false_target()->Branch(equal);
- // Smi => false iff zero.
- ASSERT(kSmiTag == 0);
- __ test(value.reg(), Operand(value.reg()));
- dest->false_target()->Branch(zero);
- __ test(value.reg(), Immediate(kSmiTagMask));
- dest->true_target()->Branch(zero);
+ // Smi => false iff zero.
+ ASSERT(kSmiTag == 0);
+ __ test(value.reg(), Operand(value.reg()));
+ dest->false_target()->Branch(zero);
+ __ test(value.reg(), Immediate(kSmiTagMask));
+ dest->true_target()->Branch(zero);
- // Call the stub for all other cases.
- frame_->Push(&value); // Undo the Pop() from above.
- ToBooleanStub stub;
- Result temp = frame_->CallStub(&stub, 1);
- // Convert the result to a condition code.
- __ test(temp.reg(), Operand(temp.reg()));
- temp.Unuse();
- dest->Split(not_equal);
+ // Call the stub for all other cases.
+ frame_->Push(&value); // Undo the Pop() from above.
+ ToBooleanStub stub;
+ Result temp = frame_->CallStub(&stub, 1);
+ // Convert the result to a condition code.
+ __ test(temp.reg(), Operand(temp.reg()));
+ temp.Unuse();
+ dest->Split(not_equal);
+ }
}
@@ -790,6 +809,10 @@
static void LoadAsIntegers(MacroAssembler* masm,
bool use_sse3,
Label* operand_conversion_failure);
+ // Test if operands are smis or heap numbers and load them
+ // into xmm0 and xmm1 if they are. Operands are in edx and eax.
+ // Leaves operands unchanged.
+ static void LoadSSE2Operands(MacroAssembler* masm);
// Test if operands are numbers (smi or HeapNumber objects), and load
// them into xmm0 and xmm1 if they are. Jump to label not_numbers if
// either operand is not a number. Operands are in edx and eax.
@@ -817,12 +840,13 @@
}
OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
- "GenericBinaryOpStub_%s_%s%s_%s%s",
+ "GenericBinaryOpStub_%s_%s%s_%s%s%s",
op_name,
overwrite_name,
(flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
args_in_registers_ ? "RegArgs" : "StackArgs",
- args_reversed_ ? "_R" : "");
+ args_reversed_ ? "_R" : "",
+ only_numbers_in_stub_ ? "_OnlyNumbers" : "");
return name_;
}
@@ -972,27 +996,35 @@
// Neither operand is known to be a string.
}
- bool left_is_smi = left.is_constant() && left.handle()->IsSmi();
- bool left_is_non_smi = left.is_constant() && !left.handle()->IsSmi();
- bool right_is_smi = right.is_constant() && right.handle()->IsSmi();
- bool right_is_non_smi = right.is_constant() && !right.handle()->IsSmi();
+ bool left_is_smi_constant = left.is_constant() && left.handle()->IsSmi();
+ bool left_is_non_smi_constant = left.is_constant() && !left.handle()->IsSmi();
+ bool right_is_smi_constant = right.is_constant() && right.handle()->IsSmi();
+ bool right_is_non_smi_constant =
+ right.is_constant() && !right.handle()->IsSmi();
- if (left_is_smi && right_is_smi) {
+ if (left_is_smi_constant && right_is_smi_constant) {
// Compute the constant result at compile time, and leave it on the frame.
int left_int = Smi::cast(*left.handle())->value();
int right_int = Smi::cast(*right.handle())->value();
if (FoldConstantSmis(op, left_int, right_int)) return;
}
+ // Get number type of left and right sub-expressions.
+ bool only_numbers = left.is_number() && right.is_number();
+ bool only_smis = left.is_smi() && right.is_smi();
+
Result answer;
- if (left_is_non_smi || right_is_non_smi) {
+ if (left_is_non_smi_constant || right_is_non_smi_constant) {
// Go straight to the slow case, with no smi code.
- GenericBinaryOpStub stub(op, overwrite_mode, NO_SMI_CODE_IN_STUB);
+ GenericBinaryOpStub stub(op,
+ overwrite_mode,
+ NO_SMI_CODE_IN_STUB,
+ only_numbers);
answer = stub.GenerateCall(masm_, frame_, &left, &right);
- } else if (right_is_smi) {
+ } else if (right_is_smi_constant) {
answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
type, false, overwrite_mode);
- } else if (left_is_smi) {
+ } else if (left_is_smi_constant) {
answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
type, true, overwrite_mode);
} else {
@@ -1004,10 +1036,49 @@
if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
} else {
- GenericBinaryOpStub stub(op, overwrite_mode, NO_GENERIC_BINARY_FLAGS);
+ GenericBinaryOpStub stub(op,
+ overwrite_mode,
+ NO_GENERIC_BINARY_FLAGS,
+ only_numbers);
answer = stub.GenerateCall(masm_, frame_, &left, &right);
}
}
+
+ // Set NumberInfo of result according to the operation performed.
+ NumberInfo::Type info = NumberInfo::kUnknown;
+ switch (op) {
+ case Token::COMMA:
+ info = right.number_info();
+ case Token::OR:
+ case Token::AND:
+ // Could be anything. Check inputs.
+ if (only_numbers)
+ info = NumberInfo::kNumber;
+ break;
+ case Token::BIT_OR:
+ case Token::BIT_XOR:
+ case Token::BIT_AND:
+ case Token::SAR:
+ case Token::SHR:
+ info = only_smis ? NumberInfo::kSmi : NumberInfo::kNumber;
+ break;
+ case Token::SHL:
+ info = NumberInfo::kNumber;
+ break;
+ case Token::ADD:
+ // Could be strings or numbers. Check types of inputs.
+ if (only_numbers) info = NumberInfo::kNumber;
+ break;
+ case Token::SUB:
+ case Token::MUL:
+ case Token::DIV:
+ case Token::MOD:
+ info = NumberInfo::kNumber;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ answer.set_number_info(info);
frame_->Push(&answer);
}
@@ -7545,7 +7616,18 @@
case Token::DIV: {
if (CpuFeatures::IsSupported(SSE2)) {
CpuFeatures::Scope use_sse2(SSE2);
- FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
+ if (only_numbers_in_stub_) {
+ if (FLAG_debug_code) {
+ // Assert at runtime that inputs are only numbers.
+ __ AbortIfNotNumber(edx,
+ "GenericBinaryOpStub operand not a number.");
+ __ AbortIfNotNumber(eax,
+ "GenericBinaryOpStub operand not a number.");
+ }
+ FloatingPointHelper::LoadSSE2Operands(masm);
+ } else {
+ FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
+ }
switch (op_) {
case Token::ADD: __ addsd(xmm0, xmm1); break;
@@ -7558,7 +7640,17 @@
__ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
GenerateReturn(masm);
} else { // SSE2 not available, use FPU.
- FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
+ if (only_numbers_in_stub_) {
+ if (FLAG_debug_code) {
+ // Assert at runtime that inputs are only numbers.
+ __ AbortIfNotNumber(edx,
+ "GenericBinaryOpStub operand not a number.");
+ __ AbortIfNotNumber(eax,
+ "GenericBinaryOpStub operand not a number.");
+ }
+ } else {
+ FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
+ }
FloatingPointHelper::LoadFloatOperands(
masm,
ecx,
@@ -8070,6 +8162,35 @@
}
+void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm) {
+ Label load_smi_edx, load_eax, load_smi_eax, done;
+ // Load operand in edx into xmm0.
+ __ test(edx, Immediate(kSmiTagMask));
+ __ j(zero, &load_smi_edx, not_taken); // Argument in edx is a smi.
+ __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset));
+
+ __ bind(&load_eax);
+ // Load operand in eax into xmm1.
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi.
+ __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset));
+ __ jmp(&done);
+
+ __ bind(&load_smi_edx);
+ __ SmiUntag(edx); // Untag smi before converting to float.
+ __ cvtsi2sd(xmm0, Operand(edx));
+ __ SmiTag(edx); // Retag smi for heap number overwriting test.
+ __ jmp(&load_eax);
+
+ __ bind(&load_smi_eax);
+ __ SmiUntag(eax); // Untag smi before converting to float.
+ __ cvtsi2sd(xmm1, Operand(eax));
+ __ SmiTag(eax); // Retag smi for heap number overwriting test.
+
+ __ bind(&done);
+}
+
+
void FloatingPointHelper::LoadSSE2Operands(MacroAssembler* masm,
Label* not_numbers) {
Label load_smi_edx, load_eax, load_smi_eax, load_float_eax, done;
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ia32/macro-assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698