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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 6812046: X64: Convert HeapNumbers that contain valid smi values to smis in binop-stub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed review comments. Created 9 years, 8 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 | « no previous file | src/x64/macro-assembler-x64.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
453 Label* not_numbers); 453 Label* not_numbers);
454 454
455 // Takes the operands in rdx and rax and loads them as integers in rax 455 // Takes the operands in rdx and rax and loads them as integers in rax
456 // and rcx. 456 // and rcx.
457 static void LoadAsIntegers(MacroAssembler* masm, 457 static void LoadAsIntegers(MacroAssembler* masm,
458 Label* operand_conversion_failure, 458 Label* operand_conversion_failure,
459 Register heap_number_map); 459 Register heap_number_map);
460 // As above, but we know the operands to be numbers. In that case, 460 // As above, but we know the operands to be numbers. In that case,
461 // conversion can't fail. 461 // conversion can't fail.
462 static void LoadNumbersAsIntegers(MacroAssembler* masm); 462 static void LoadNumbersAsIntegers(MacroAssembler* masm);
463
464 // Tries to convert two values to smis losslessly.
465 // This fails if either argument is not a Smi nor a HeapNumber,
466 // or if it's a HeapNumber with a value that can't be converted
467 // losslessly to a Smi. In that case, control transitions to the
468 // on_not_smis label.
469 // On success, either control goes to the on_success label,
470 // or it falls through at the end of the code.
471 // (If you just want to fall through in all cases, put the success
William Hesse 2011/04/08 12:01:27 Why let the user of this function make a mistake.
Lasse Reichstein 2011/04/08 12:07:46 Done.
472 // label at the fall-through point).
473 // At this point, both first and second holds Smi tagged values.
474 // One of first or second must be non-Smi.
475 static void NumbersToSmis(MacroAssembler* masm,
476 Register first,
477 Register second,
478 Register scratch1,
479 Register scratch2,
480 Register scratch3,
481 Label* on_success,
482 Label* on_not_smis);
463 }; 483 };
464 484
465 485
466 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) { 486 void GenericBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, Label* slow) {
467 // 1. Move arguments into rdx, rax except for DIV and MOD, which need the 487 // 1. Move arguments into rdx, rax except for DIV and MOD, which need the
468 // dividend in rax and rdx free for the division. Use rax, rbx for those. 488 // dividend in rax and rdx free for the division. Use rax, rbx for those.
469 Comment load_comment(masm, "-- Load arguments"); 489 Comment load_comment(masm, "-- Load arguments");
470 Register left = rdx; 490 Register left = rdx;
471 Register right = rax; 491 Register right = rax;
472 if (op_ == Token::DIV || op_ == Token::MOD) { 492 if (op_ == Token::DIV || op_ == Token::MOD) {
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
1098 overwrite_name, 1118 overwrite_name,
1099 TRBinaryOpIC::GetName(operands_type_)); 1119 TRBinaryOpIC::GetName(operands_type_));
1100 return name_; 1120 return name_;
1101 } 1121 }
1102 1122
1103 1123
1104 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm, 1124 void TypeRecordingBinaryOpStub::GenerateSmiCode(MacroAssembler* masm,
1105 Label* slow, 1125 Label* slow,
1106 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { 1126 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
1107 1127
1128 // Arguments to TypeRecordingBinaryOpStub are in rdx and rax.
1129 Register left = rdx;
1130 Register right = rax;
1131
1108 // We only generate heapnumber answers for overflowing calculations 1132 // We only generate heapnumber answers for overflowing calculations
1109 // for the four basic arithmetic operations. 1133 // for the four basic arithmetic operations and logical right shift by 0.
1110 bool generate_inline_heapnumber_results = 1134 bool generate_inline_heapnumber_results =
1111 (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) && 1135 (allow_heapnumber_results == ALLOW_HEAPNUMBER_RESULTS) &&
1112 (op_ == Token::ADD || op_ == Token::SUB || 1136 (op_ == Token::ADD || op_ == Token::SUB ||
1113 op_ == Token::MUL || op_ == Token::DIV || op_ == Token::SHR); 1137 op_ == Token::MUL || op_ == Token::DIV || op_ == Token::SHR);
1114 1138
1115 // Arguments to TypeRecordingBinaryOpStub are in rdx and rax.
1116 Register left = rdx;
1117 Register right = rax;
1118
1119
1120 // Smi check of both operands. If op is BIT_OR, the check is delayed 1139 // Smi check of both operands. If op is BIT_OR, the check is delayed
1121 // until after the OR operation. 1140 // until after the OR operation.
1122 Label not_smis; 1141 Label not_smis;
1123 Label use_fp_on_smis; 1142 Label use_fp_on_smis;
1124 Label restore_MOD_registers; // Only used if op_ == Token::MOD. 1143 Label fail;
1125 1144
1126 if (op_ != Token::BIT_OR) { 1145 if (op_ != Token::BIT_OR) {
1127 Comment smi_check_comment(masm, "-- Smi check arguments"); 1146 Comment smi_check_comment(masm, "-- Smi check arguments");
1128 __ JumpIfNotBothSmi(left, right, &not_smis); 1147 __ JumpIfNotBothSmi(left, right, &not_smis);
1129 } 1148 }
1130 1149
1150 Label smi_values;
1151 __ bind(&smi_values);
1131 // Perform the operation. 1152 // Perform the operation.
1132 Comment perform_smi(masm, "-- Perform smi operation"); 1153 Comment perform_smi(masm, "-- Perform smi operation");
1133 switch (op_) { 1154 switch (op_) {
1134 case Token::ADD: 1155 case Token::ADD:
1135 ASSERT(right.is(rax)); 1156 ASSERT(right.is(rax));
1136 __ SmiAdd(right, right, left, &use_fp_on_smis); // ADD is commutative. 1157 __ SmiAdd(right, right, left, &use_fp_on_smis); // ADD is commutative.
1137 break; 1158 break;
1138 1159
1139 case Token::SUB: 1160 case Token::SUB:
1140 __ SmiSub(left, left, right, &use_fp_on_smis); 1161 __ SmiSub(left, left, right, &use_fp_on_smis);
(...skipping 18 matching lines...) Expand all
1159 // SmiMod will not accept left in rdx or right in rax. 1180 // SmiMod will not accept left in rdx or right in rax.
1160 left = rcx; 1181 left = rcx;
1161 right = rbx; 1182 right = rbx;
1162 __ movq(rbx, rax); 1183 __ movq(rbx, rax);
1163 __ movq(rcx, rdx); 1184 __ movq(rcx, rdx);
1164 __ SmiMod(rax, left, right, &use_fp_on_smis); 1185 __ SmiMod(rax, left, right, &use_fp_on_smis);
1165 break; 1186 break;
1166 1187
1167 case Token::BIT_OR: { 1188 case Token::BIT_OR: {
1168 ASSERT(right.is(rax)); 1189 ASSERT(right.is(rax));
1169 __ movq(rcx, right); // Save the right operand. 1190 __ SmiOrIfSmis(right, right, left, &not_smis); // BIT_OR is commutative.
1170 __ SmiOr(right, right, left); // BIT_OR is commutative.
1171 __ JumpIfNotSmi(right, &not_smis); // Test delayed until after BIT_OR.
1172 break; 1191 break;
1173 } 1192 }
1174 case Token::BIT_XOR: 1193 case Token::BIT_XOR:
1175 ASSERT(right.is(rax)); 1194 ASSERT(right.is(rax));
1176 __ SmiXor(right, right, left); // BIT_XOR is commutative. 1195 __ SmiXor(right, right, left); // BIT_XOR is commutative.
1177 break; 1196 break;
1178 1197
1179 case Token::BIT_AND: 1198 case Token::BIT_AND:
1180 ASSERT(right.is(rax)); 1199 ASSERT(right.is(rax));
1181 __ SmiAnd(right, right, left); // BIT_AND is commutative. 1200 __ SmiAnd(right, right, left); // BIT_AND is commutative.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1226 case Token::ADD: __ addsd(xmm0, xmm1); break; 1245 case Token::ADD: __ addsd(xmm0, xmm1); break;
1227 case Token::SUB: __ subsd(xmm0, xmm1); break; 1246 case Token::SUB: __ subsd(xmm0, xmm1); break;
1228 case Token::MUL: __ mulsd(xmm0, xmm1); break; 1247 case Token::MUL: __ mulsd(xmm0, xmm1); break;
1229 case Token::DIV: __ divsd(xmm0, xmm1); break; 1248 case Token::DIV: __ divsd(xmm0, xmm1); break;
1230 default: UNREACHABLE(); 1249 default: UNREACHABLE();
1231 } 1250 }
1232 } 1251 }
1233 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 1252 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
1234 __ movq(rax, rcx); 1253 __ movq(rax, rcx);
1235 __ ret(0); 1254 __ ret(0);
1255 } else {
1256 __ jmp(&fail);
1236 } 1257 }
1237 } 1258 }
1238 1259
1239 // 7. Non-smi operands reach the end of the code generated by 1260 // 7. Non-smi operands reach the end of the code generated by
1240 // GenerateSmiCode, and fall through to subsequent code, 1261 // GenerateSmiCode, and fall through to subsequent code,
1241 // with the operands in rdx and rax. 1262 // with the operands in rdx and rax.
1263 // But first we check if non-smi values are HeapNumbers holding
1264 // values that could be smi.
1265 __ bind(&not_smis);
1242 Comment done_comment(masm, "-- Enter non-smi code"); 1266 Comment done_comment(masm, "-- Enter non-smi code");
1243 __ bind(&not_smis); 1267 FloatingPointHelper::NumbersToSmis(masm, left, right, rbx, rdi, rcx,
1244 if (op_ == Token::BIT_OR) { 1268 &smi_values, &fail);
1245 __ movq(right, rcx); 1269 __ jmp(&smi_values);
1246 } 1270 __ bind(&fail);
1247 } 1271 }
1248 1272
1249 1273
1250 void TypeRecordingBinaryOpStub::GenerateFloatingPointCode( 1274 void TypeRecordingBinaryOpStub::GenerateFloatingPointCode(
1251 MacroAssembler* masm, 1275 MacroAssembler* masm,
1252 Label* allocation_failure, 1276 Label* allocation_failure,
1253 Label* non_numeric_failure) { 1277 Label* non_numeric_failure) {
1254 switch (op_) { 1278 switch (op_) {
1255 case Token::ADD: 1279 case Token::ADD:
1256 case Token::SUB: 1280 case Token::SUB:
(...skipping 801 matching lines...) Expand 10 before | Expand all | Expand 10 after
2058 __ cvtlsi2sd(xmm0, kScratchRegister); 2082 __ cvtlsi2sd(xmm0, kScratchRegister);
2059 __ JumpIfNotSmi(rax, &load_nonsmi_rax); 2083 __ JumpIfNotSmi(rax, &load_nonsmi_rax);
2060 2084
2061 __ bind(&load_smi_rax); 2085 __ bind(&load_smi_rax);
2062 __ SmiToInteger32(kScratchRegister, rax); 2086 __ SmiToInteger32(kScratchRegister, rax);
2063 __ cvtlsi2sd(xmm1, kScratchRegister); 2087 __ cvtlsi2sd(xmm1, kScratchRegister);
2064 __ bind(&done); 2088 __ bind(&done);
2065 } 2089 }
2066 2090
2067 2091
2092 void FloatingPointHelper::NumbersToSmis(MacroAssembler* masm,
2093 Register first,
2094 Register second,
2095 Register scratch1,
2096 Register scratch2,
2097 Register scratch3,
2098 Label* on_success,
2099 Label* on_not_smis) {
2100 Register heap_number_root = scratch3;
2101 Register smi_result = scratch1;
2102 __ LoadRoot(heap_number_root, Heap::kHeapNumberMapRootIndex);
William Hesse 2011/04/08 12:01:27 Shouldn't this be called heap_number_map?
Lasse Reichstein 2011/04/08 12:07:46 Absolutely.
2103
2104 NearLabel first_smi, check_second;
2105 __ JumpIfSmi(first, &first_smi);
2106 __ cmpq(FieldOperand(first, HeapObject::kMapOffset), heap_number_root);
2107 __ j(not_equal, on_not_smis);
2108 // Convert HeapNumber to smi if possible.
2109 __ movsd(xmm0, FieldOperand(first, HeapNumber::kValueOffset));
2110 __ movq(scratch2, xmm0);
2111 __ cvttsd2siq(smi_result, xmm0);
2112 // Check if conversion was successful by converting back and
2113 // comparing to the original double's bits.
2114 __ cvtlsi2sd(xmm1, smi_result);
2115 __ movq(kScratchRegister, xmm1);
2116 __ cmpq(scratch2, kScratchRegister);
2117 __ j(not_equal, on_not_smis);
2118 __ Integer32ToSmi(first, smi_result);
2119
2120 __ bind(&check_second);
2121 __ JumpIfSmi(second, on_success);
2122 __ bind(&first_smi);
2123 if (FLAG_debug_code) {
2124 // One of first or second should be non-smi if we get here.
William Hesse 2011/04/08 12:01:27 Second should be non-smi if we get here.
Lasse Reichstein 2011/04/08 12:07:46 Done.
2125 __ AbortIfSmi(second);
2126 }
2127 __ cmpq(FieldOperand(second, HeapObject::kMapOffset), heap_number_root);
2128 __ j(not_equal, on_not_smis);
2129 // Convert second to smi, if possible.
2130 __ movsd(xmm0, FieldOperand(second, HeapNumber::kValueOffset));
2131 __ movq(scratch2, xmm0);
2132 __ cvttsd2siq(smi_result, xmm0);
2133 __ cvtlsi2sd(xmm1, smi_result);
2134 __ movq(kScratchRegister, xmm1);
2135 __ cmpq(scratch2, kScratchRegister);
2136 __ j(not_equal, on_not_smis);
2137 __ Integer32ToSmi(second, smi_result);
2138 }
2139
2140
2068 void GenericUnaryOpStub::Generate(MacroAssembler* masm) { 2141 void GenericUnaryOpStub::Generate(MacroAssembler* masm) {
2069 Label slow, done; 2142 Label slow, done;
2070 2143
2071 if (op_ == Token::SUB) { 2144 if (op_ == Token::SUB) {
2072 if (include_smi_code_) { 2145 if (include_smi_code_) {
2073 // Check whether the value is a smi. 2146 // Check whether the value is a smi.
2074 Label try_float; 2147 Label try_float;
2075 __ JumpIfNotSmi(rax, &try_float); 2148 __ JumpIfNotSmi(rax, &try_float);
2076 if (negative_zero_ == kIgnoreNegativeZero) { 2149 if (negative_zero_ == kIgnoreNegativeZero) {
2077 __ SmiCompare(rax, Smi::FromInt(0)); 2150 __ SmiCompare(rax, Smi::FromInt(0));
(...skipping 3064 matching lines...) Expand 10 before | Expand all | Expand 10 after
5142 // Do a tail call to the rewritten stub. 5215 // Do a tail call to the rewritten stub.
5143 __ jmp(rdi); 5216 __ jmp(rdi);
5144 } 5217 }
5145 5218
5146 5219
5147 #undef __ 5220 #undef __
5148 5221
5149 } } // namespace v8::internal 5222 } } // namespace v8::internal
5150 5223
5151 #endif // V8_TARGET_ARCH_X64 5224 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « no previous file | src/x64/macro-assembler-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698