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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 593110: Pass the complete number type information into the GenericBinaryOpStub.... (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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/number-info.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 822 matching lines...) Expand 10 before | Expand all | Expand 10 after
833 const char* op_name = Token::Name(op_); 833 const char* op_name = Token::Name(op_);
834 const char* overwrite_name; 834 const char* overwrite_name;
835 switch (mode_) { 835 switch (mode_) {
836 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 836 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
837 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 837 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
838 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 838 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
839 default: overwrite_name = "UnknownOverwrite"; break; 839 default: overwrite_name = "UnknownOverwrite"; break;
840 } 840 }
841 841
842 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 842 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
843 "GenericBinaryOpStub_%s_%s%s_%s%s%s", 843 "GenericBinaryOpStub_%s_%s%s_%s%s_%s",
844 op_name, 844 op_name,
845 overwrite_name, 845 overwrite_name,
846 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "", 846 (flags_ & NO_SMI_CODE_IN_STUB) ? "_NoSmiInStub" : "",
847 args_in_registers_ ? "RegArgs" : "StackArgs", 847 args_in_registers_ ? "RegArgs" : "StackArgs",
848 args_reversed_ ? "_R" : "", 848 args_reversed_ ? "_R" : "",
849 only_numbers_in_stub_ ? "_OnlyNumbers" : ""); 849 NumberInfo::ToString(operands_type_));
850 return name_; 850 return name_;
851 } 851 }
852 852
853 853
854 // Call the specialized stub for a binary operation. 854 // Call the specialized stub for a binary operation.
855 class DeferredInlineBinaryOperation: public DeferredCode { 855 class DeferredInlineBinaryOperation: public DeferredCode {
856 public: 856 public:
857 DeferredInlineBinaryOperation(Token::Value op, 857 DeferredInlineBinaryOperation(Token::Value op,
858 Register dst, 858 Register dst,
859 Register left, 859 Register left,
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 right.is_constant() && !right.handle()->IsSmi(); 1003 right.is_constant() && !right.handle()->IsSmi();
1004 1004
1005 if (left_is_smi_constant && right_is_smi_constant) { 1005 if (left_is_smi_constant && right_is_smi_constant) {
1006 // Compute the constant result at compile time, and leave it on the frame. 1006 // Compute the constant result at compile time, and leave it on the frame.
1007 int left_int = Smi::cast(*left.handle())->value(); 1007 int left_int = Smi::cast(*left.handle())->value();
1008 int right_int = Smi::cast(*right.handle())->value(); 1008 int right_int = Smi::cast(*right.handle())->value();
1009 if (FoldConstantSmis(op, left_int, right_int)) return; 1009 if (FoldConstantSmis(op, left_int, right_int)) return;
1010 } 1010 }
1011 1011
1012 // Get number type of left and right sub-expressions. 1012 // Get number type of left and right sub-expressions.
1013 bool only_numbers = left.is_number() && right.is_number(); 1013 NumberInfo::Type operands_type =
1014 bool only_smis = left.is_smi() && right.is_smi(); 1014 NumberInfo::Combine(left.number_info(), right.number_info());
1015 1015
1016 Result answer; 1016 Result answer;
1017 if (left_is_non_smi_constant || right_is_non_smi_constant) { 1017 if (left_is_non_smi_constant || right_is_non_smi_constant) {
1018 // Go straight to the slow case, with no smi code. 1018 // Go straight to the slow case, with no smi code.
1019 GenericBinaryOpStub stub(op, 1019 GenericBinaryOpStub stub(op,
1020 overwrite_mode, 1020 overwrite_mode,
1021 NO_SMI_CODE_IN_STUB, 1021 NO_SMI_CODE_IN_STUB,
1022 only_numbers); 1022 operands_type);
1023 answer = stub.GenerateCall(masm_, frame_, &left, &right); 1023 answer = stub.GenerateCall(masm_, frame_, &left, &right);
1024 } else if (right_is_smi_constant) { 1024 } else if (right_is_smi_constant) {
1025 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), 1025 answer = ConstantSmiBinaryOperation(op, &left, right.handle(),
1026 type, false, overwrite_mode); 1026 type, false, overwrite_mode);
1027 } else if (left_is_smi_constant) { 1027 } else if (left_is_smi_constant) {
1028 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), 1028 answer = ConstantSmiBinaryOperation(op, &right, left.handle(),
1029 type, true, overwrite_mode); 1029 type, true, overwrite_mode);
1030 } else { 1030 } else {
1031 // Set the flags based on the operation, type and loop nesting level. 1031 // Set the flags based on the operation, type and loop nesting level.
1032 // Bit operations always assume they likely operate on Smis. Still only 1032 // Bit operations always assume they likely operate on Smis. Still only
1033 // generate the inline Smi check code if this operation is part of a loop. 1033 // generate the inline Smi check code if this operation is part of a loop.
1034 // For all other operations only inline the Smi check code for likely smis 1034 // For all other operations only inline the Smi check code for likely smis
1035 // if the operation is part of a loop. 1035 // if the operation is part of a loop.
1036 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) { 1036 if (loop_nesting() > 0 && (Token::IsBitOp(op) || type->IsLikelySmi())) {
1037 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); 1037 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode);
1038 } else { 1038 } else {
1039 GenericBinaryOpStub stub(op, 1039 GenericBinaryOpStub stub(op,
1040 overwrite_mode, 1040 overwrite_mode,
1041 NO_GENERIC_BINARY_FLAGS, 1041 NO_GENERIC_BINARY_FLAGS,
1042 only_numbers); 1042 operands_type);
1043 answer = stub.GenerateCall(masm_, frame_, &left, &right); 1043 answer = stub.GenerateCall(masm_, frame_, &left, &right);
1044 } 1044 }
1045 } 1045 }
1046 1046
1047 // Set NumberInfo of result according to the operation performed. 1047 // Set NumberInfo of result according to the operation performed.
1048 NumberInfo::Type info = NumberInfo::kUnknown; 1048 // Rely on the fact that smis have a 31 bit payload on ia32.
1049 ASSERT(kSmiValueSize == 31);
1050 NumberInfo::Type result_type = NumberInfo::kUnknown;
1049 switch (op) { 1051 switch (op) {
1050 case Token::COMMA: 1052 case Token::COMMA:
1051 info = right.number_info(); 1053 result_type = right.number_info();
1054 break;
1052 case Token::OR: 1055 case Token::OR:
1053 case Token::AND: 1056 case Token::AND:
1054 // Could be anything. Check inputs. 1057 // Result type can be either of the two input types.
1055 if (only_numbers) 1058 result_type = operands_type;
1056 info = NumberInfo::kNumber;
1057 break; 1059 break;
1058 case Token::BIT_OR: 1060 case Token::BIT_OR:
1059 case Token::BIT_XOR: 1061 case Token::BIT_XOR:
1060 case Token::BIT_AND: 1062 case Token::BIT_AND:
1063 // Result is always a number. Smi property of inputs is preserved.
1064 result_type = (operands_type == NumberInfo::kSmi)
1065 ? NumberInfo::kSmi
1066 : NumberInfo::kNumber;
1067 break;
1061 case Token::SAR: 1068 case Token::SAR:
1069 // Result is a smi if we shift by a constant >= 1, otherwise a number.
1070 result_type = (right.is_constant() && right.handle()->IsSmi()
1071 && Smi::cast(*right.handle())->value() >= 1)
1072 ? NumberInfo::kSmi
1073 : NumberInfo::kNumber;
1074 break;
1062 case Token::SHR: 1075 case Token::SHR:
1063 info = only_smis ? NumberInfo::kSmi : NumberInfo::kNumber; 1076 // Result is a smi if we shift by a constant >= 2, otherwise a number.
1077 result_type = (right.is_constant() && right.handle()->IsSmi()
1078 && Smi::cast(*right.handle())->value() >= 2)
1079 ? NumberInfo::kSmi
1080 : NumberInfo::kNumber;
1081 break;
1082 case Token::ADD:
1083 // Result could be a string or a number. Check types of inputs.
1084 result_type = NumberInfo::IsNumber(operands_type)
1085 ? NumberInfo::kNumber
1086 : NumberInfo::kUnknown;
1064 break; 1087 break;
1065 case Token::SHL: 1088 case Token::SHL:
1066 info = NumberInfo::kNumber;
1067 break;
1068 case Token::ADD:
1069 // Could be strings or numbers. Check types of inputs.
1070 if (only_numbers) info = NumberInfo::kNumber;
1071 break;
1072 case Token::SUB: 1089 case Token::SUB:
1073 case Token::MUL: 1090 case Token::MUL:
1074 case Token::DIV: 1091 case Token::DIV:
1075 case Token::MOD: 1092 case Token::MOD:
1076 info = NumberInfo::kNumber; 1093 // Result is always a number.
1094 result_type = NumberInfo::kNumber;
1077 break; 1095 break;
1078 default: 1096 default:
1079 UNREACHABLE(); 1097 UNREACHABLE();
1080 } 1098 }
1081 answer.set_number_info(info); 1099 answer.set_number_info(result_type);
1082 frame_->Push(&answer); 1100 frame_->Push(&answer);
1083 } 1101 }
1084 1102
1085 1103
1086 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) { 1104 bool CodeGenerator::FoldConstantSmis(Token::Value op, int left, int right) {
1087 Object* answer_object = Heap::undefined_value(); 1105 Object* answer_object = Heap::undefined_value();
1088 switch (op) { 1106 switch (op) {
1089 case Token::ADD: 1107 case Token::ADD:
1090 if (Smi::IsValid(left + right)) { 1108 if (Smi::IsValid(left + right)) {
1091 answer_object = Smi::FromInt(left + right); 1109 answer_object = Smi::FromInt(left + right);
(...skipping 6517 matching lines...) Expand 10 before | Expand all | Expand 10 after
7609 } 7627 }
7610 7628
7611 // Floating point case. 7629 // Floating point case.
7612 switch (op_) { 7630 switch (op_) {
7613 case Token::ADD: 7631 case Token::ADD:
7614 case Token::SUB: 7632 case Token::SUB:
7615 case Token::MUL: 7633 case Token::MUL:
7616 case Token::DIV: { 7634 case Token::DIV: {
7617 if (CpuFeatures::IsSupported(SSE2)) { 7635 if (CpuFeatures::IsSupported(SSE2)) {
7618 CpuFeatures::Scope use_sse2(SSE2); 7636 CpuFeatures::Scope use_sse2(SSE2);
7619 if (only_numbers_in_stub_) { 7637 if (NumberInfo::IsNumber(operands_type_)) {
7620 if (FLAG_debug_code) { 7638 if (FLAG_debug_code) {
7621 // Assert at runtime that inputs are only numbers. 7639 // Assert at runtime that inputs are only numbers.
7622 __ AbortIfNotNumber(edx, 7640 __ AbortIfNotNumber(edx,
7623 "GenericBinaryOpStub operand not a number."); 7641 "GenericBinaryOpStub operand not a number.");
7624 __ AbortIfNotNumber(eax, 7642 __ AbortIfNotNumber(eax,
7625 "GenericBinaryOpStub operand not a number."); 7643 "GenericBinaryOpStub operand not a number.");
7626 } 7644 }
7627 FloatingPointHelper::LoadSSE2Operands(masm); 7645 FloatingPointHelper::LoadSSE2Operands(masm);
7628 } else { 7646 } else {
7629 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime); 7647 FloatingPointHelper::LoadSSE2Operands(masm, &call_runtime);
7630 } 7648 }
7631 7649
7632 switch (op_) { 7650 switch (op_) {
7633 case Token::ADD: __ addsd(xmm0, xmm1); break; 7651 case Token::ADD: __ addsd(xmm0, xmm1); break;
7634 case Token::SUB: __ subsd(xmm0, xmm1); break; 7652 case Token::SUB: __ subsd(xmm0, xmm1); break;
7635 case Token::MUL: __ mulsd(xmm0, xmm1); break; 7653 case Token::MUL: __ mulsd(xmm0, xmm1); break;
7636 case Token::DIV: __ divsd(xmm0, xmm1); break; 7654 case Token::DIV: __ divsd(xmm0, xmm1); break;
7637 default: UNREACHABLE(); 7655 default: UNREACHABLE();
7638 } 7656 }
7639 GenerateHeapResultAllocation(masm, &call_runtime); 7657 GenerateHeapResultAllocation(masm, &call_runtime);
7640 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); 7658 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0);
7641 GenerateReturn(masm); 7659 GenerateReturn(masm);
7642 } else { // SSE2 not available, use FPU. 7660 } else { // SSE2 not available, use FPU.
7643 if (only_numbers_in_stub_) { 7661 if (NumberInfo::IsNumber(operands_type_)) {
7644 if (FLAG_debug_code) { 7662 if (FLAG_debug_code) {
7645 // Assert at runtime that inputs are only numbers. 7663 // Assert at runtime that inputs are only numbers.
7646 __ AbortIfNotNumber(edx, 7664 __ AbortIfNotNumber(edx,
7647 "GenericBinaryOpStub operand not a number."); 7665 "GenericBinaryOpStub operand not a number.");
7648 __ AbortIfNotNumber(eax, 7666 __ AbortIfNotNumber(eax,
7649 "GenericBinaryOpStub operand not a number."); 7667 "GenericBinaryOpStub operand not a number.");
7650 } 7668 }
7651 } else { 7669 } else {
7652 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx); 7670 FloatingPointHelper::CheckFloatOperands(masm, &call_runtime, ebx);
7653 } 7671 }
(...skipping 2892 matching lines...) Expand 10 before | Expand all | Expand 10 after
10546 10564
10547 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 10565 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
10548 // tagged as a small integer. 10566 // tagged as a small integer.
10549 __ bind(&runtime); 10567 __ bind(&runtime);
10550 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1); 10568 __ TailCallRuntime(ExternalReference(Runtime::kStringCompare), 2, 1);
10551 } 10569 }
10552 10570
10553 #undef __ 10571 #undef __
10554 10572
10555 } } // namespace v8::internal 10573 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/number-info.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698