OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1265 default: UNREACHABLE(); break; | 1265 default: UNREACHABLE(); break; |
1266 } | 1266 } |
1267 // No fall-through from this generated code. | 1267 // No fall-through from this generated code. |
1268 if (FLAG_debug_code) { | 1268 if (FLAG_debug_code) { |
1269 __ Abort("Unexpected fall-through in " | 1269 __ Abort("Unexpected fall-through in " |
1270 "BinaryStub_GenerateFloatingPointCode."); | 1270 "BinaryStub_GenerateFloatingPointCode."); |
1271 } | 1271 } |
1272 } | 1272 } |
1273 | 1273 |
1274 | 1274 |
| 1275 static void BinaryOpStub_GenerateRegisterArgsPushUnderReturn( |
| 1276 MacroAssembler* masm) { |
| 1277 // Push arguments, but ensure they are under the return address |
| 1278 // for a tail call. |
| 1279 __ pop(rcx); |
| 1280 __ push(rdx); |
| 1281 __ push(rax); |
| 1282 __ push(rcx); |
| 1283 } |
| 1284 |
| 1285 |
1275 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { | 1286 void BinaryOpStub::GenerateAddStrings(MacroAssembler* masm) { |
1276 ASSERT(op_ == Token::ADD); | 1287 ASSERT(op_ == Token::ADD); |
1277 Label left_not_string, call_runtime; | 1288 Label left_not_string, call_runtime; |
1278 | 1289 |
1279 // Registers containing left and right operands respectively. | 1290 // Registers containing left and right operands respectively. |
1280 Register left = rdx; | 1291 Register left = rdx; |
1281 Register right = rax; | 1292 Register right = rax; |
1282 | 1293 |
1283 // Test if left operand is a string. | 1294 // Test if left operand is a string. |
1284 __ JumpIfSmi(left, &left_not_string, Label::kNear); | 1295 __ JumpIfSmi(left, &left_not_string, Label::kNear); |
1285 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx); | 1296 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx); |
1286 __ j(above_equal, &left_not_string, Label::kNear); | 1297 __ j(above_equal, &left_not_string, Label::kNear); |
1287 StringAddStub string_add_left_stub(NO_STRING_CHECK_LEFT_IN_STUB); | 1298 StringAddStub string_add_left_stub((StringAddFlags) |
1288 GenerateRegisterArgsPush(masm); | 1299 (ERECT_FRAME | NO_STRING_CHECK_LEFT_IN_STUB)); |
| 1300 BinaryOpStub_GenerateRegisterArgsPushUnderReturn(masm); |
1289 __ TailCallStub(&string_add_left_stub); | 1301 __ TailCallStub(&string_add_left_stub); |
1290 | 1302 |
1291 // Left operand is not a string, test right. | 1303 // Left operand is not a string, test right. |
1292 __ bind(&left_not_string); | 1304 __ bind(&left_not_string); |
1293 __ JumpIfSmi(right, &call_runtime, Label::kNear); | 1305 __ JumpIfSmi(right, &call_runtime, Label::kNear); |
1294 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx); | 1306 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx); |
1295 __ j(above_equal, &call_runtime, Label::kNear); | 1307 __ j(above_equal, &call_runtime, Label::kNear); |
1296 | 1308 |
1297 StringAddStub string_add_right_stub(NO_STRING_CHECK_RIGHT_IN_STUB); | 1309 StringAddStub string_add_right_stub((StringAddFlags) |
1298 GenerateRegisterArgsPush(masm); | 1310 (ERECT_FRAME | NO_STRING_CHECK_RIGHT_IN_STUB)); |
| 1311 BinaryOpStub_GenerateRegisterArgsPushUnderReturn(masm); |
1299 __ TailCallStub(&string_add_right_stub); | 1312 __ TailCallStub(&string_add_right_stub); |
1300 | 1313 |
1301 // Neither argument is a string. | 1314 // Neither argument is a string. |
1302 __ bind(&call_runtime); | 1315 __ bind(&call_runtime); |
1303 } | 1316 } |
1304 | 1317 |
1305 | 1318 |
1306 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { | 1319 void BinaryOpStub::GenerateSmiStub(MacroAssembler* masm) { |
1307 Label call_runtime; | 1320 Label call_runtime; |
1308 if (result_type_ == BinaryOpIC::UNINITIALIZED || | 1321 if (result_type_ == BinaryOpIC::UNINITIALIZED || |
1309 result_type_ == BinaryOpIC::SMI) { | 1322 result_type_ == BinaryOpIC::SMI) { |
1310 // Only allow smi results. | 1323 // Only allow smi results. |
1311 BinaryOpStub_GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS, op_); | 1324 BinaryOpStub_GenerateSmiCode(masm, NULL, NO_HEAPNUMBER_RESULTS, op_); |
1312 } else { | 1325 } else { |
1313 // Allow heap number result and don't make a transition if a heap number | 1326 // Allow heap number result and don't make a transition if a heap number |
1314 // cannot be allocated. | 1327 // cannot be allocated. |
1315 BinaryOpStub_GenerateSmiCode( | 1328 BinaryOpStub_GenerateSmiCode( |
1316 masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS, op_); | 1329 masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS, op_); |
1317 } | 1330 } |
1318 | 1331 |
1319 // Code falls through if the result is not returned as either a smi or heap | 1332 // Code falls through if the result is not returned as either a smi or heap |
1320 // number. | 1333 // number. |
1321 GenerateTypeTransition(masm); | 1334 GenerateTypeTransition(masm); |
1322 | 1335 |
1323 if (call_runtime.is_linked()) { | 1336 if (call_runtime.is_linked()) { |
1324 __ bind(&call_runtime); | 1337 __ bind(&call_runtime); |
1325 GenerateRegisterArgsPush(masm); | 1338 { |
1326 GenerateCallRuntime(masm); | 1339 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1340 GenerateRegisterArgsPush(masm); |
| 1341 GenerateCallRuntime(masm); |
| 1342 } |
| 1343 __ Ret(); |
1327 } | 1344 } |
1328 } | 1345 } |
1329 | 1346 |
1330 | 1347 |
1331 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 1348 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
1332 // The int32 case is identical to the Smi case. We avoid creating this | 1349 // The int32 case is identical to the Smi case. We avoid creating this |
1333 // ic state on x64. | 1350 // ic state on x64. |
1334 UNREACHABLE(); | 1351 UNREACHABLE(); |
1335 } | 1352 } |
1336 | 1353 |
(...skipping 12 matching lines...) Expand all Loading... |
1349 // Test if left operand is a string. | 1366 // Test if left operand is a string. |
1350 __ JumpIfSmi(left, &call_runtime); | 1367 __ JumpIfSmi(left, &call_runtime); |
1351 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx); | 1368 __ CmpObjectType(left, FIRST_NONSTRING_TYPE, rcx); |
1352 __ j(above_equal, &call_runtime); | 1369 __ j(above_equal, &call_runtime); |
1353 | 1370 |
1354 // Test if right operand is a string. | 1371 // Test if right operand is a string. |
1355 __ JumpIfSmi(right, &call_runtime); | 1372 __ JumpIfSmi(right, &call_runtime); |
1356 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx); | 1373 __ CmpObjectType(right, FIRST_NONSTRING_TYPE, rcx); |
1357 __ j(above_equal, &call_runtime); | 1374 __ j(above_equal, &call_runtime); |
1358 | 1375 |
1359 StringAddStub string_add_stub(NO_STRING_CHECK_IN_STUB); | 1376 StringAddStub string_add_stub((StringAddFlags) |
1360 GenerateRegisterArgsPush(masm); | 1377 (ERECT_FRAME | NO_STRING_CHECK_IN_STUB)); |
| 1378 BinaryOpStub_GenerateRegisterArgsPushUnderReturn(masm); |
1361 __ TailCallStub(&string_add_stub); | 1379 __ TailCallStub(&string_add_stub); |
1362 | 1380 |
1363 __ bind(&call_runtime); | 1381 __ bind(&call_runtime); |
1364 GenerateTypeTransition(masm); | 1382 GenerateTypeTransition(masm); |
1365 } | 1383 } |
1366 | 1384 |
1367 | 1385 |
1368 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { | 1386 void BinaryOpStub::GenerateOddballStub(MacroAssembler* masm) { |
1369 Label call_runtime; | 1387 Label call_runtime; |
1370 | 1388 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1435 BinaryOpStub_CheckSmiInput(masm, rax, ¬_number); | 1453 BinaryOpStub_CheckSmiInput(masm, rax, ¬_number); |
1436 } | 1454 } |
1437 | 1455 |
1438 BinaryOpStub_GenerateFloatingPointCode( | 1456 BinaryOpStub_GenerateFloatingPointCode( |
1439 masm, &gc_required, ¬_number, op_, mode_); | 1457 masm, &gc_required, ¬_number, op_, mode_); |
1440 | 1458 |
1441 __ bind(¬_number); | 1459 __ bind(¬_number); |
1442 GenerateTypeTransition(masm); | 1460 GenerateTypeTransition(masm); |
1443 | 1461 |
1444 __ bind(&gc_required); | 1462 __ bind(&gc_required); |
1445 GenerateRegisterArgsPush(masm); | 1463 { |
1446 GenerateCallRuntime(masm); | 1464 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1465 GenerateRegisterArgsPush(masm); |
| 1466 GenerateCallRuntime(masm); |
| 1467 } |
| 1468 __ Ret(); |
1447 } | 1469 } |
1448 | 1470 |
1449 | 1471 |
1450 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) { | 1472 void BinaryOpStub::GenerateGeneric(MacroAssembler* masm) { |
1451 Label call_runtime, call_string_add_or_runtime; | 1473 Label call_runtime, call_string_add_or_runtime; |
1452 | 1474 |
1453 BinaryOpStub_GenerateSmiCode( | 1475 BinaryOpStub_GenerateSmiCode( |
1454 masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS, op_); | 1476 masm, &call_runtime, ALLOW_HEAPNUMBER_RESULTS, op_); |
1455 | 1477 |
1456 BinaryOpStub_GenerateFloatingPointCode( | 1478 BinaryOpStub_GenerateFloatingPointCode( |
1457 masm, &call_runtime, &call_string_add_or_runtime, op_, mode_); | 1479 masm, &call_runtime, &call_string_add_or_runtime, op_, mode_); |
1458 | 1480 |
1459 __ bind(&call_string_add_or_runtime); | 1481 __ bind(&call_string_add_or_runtime); |
1460 if (op_ == Token::ADD) { | 1482 if (op_ == Token::ADD) { |
1461 GenerateAddStrings(masm); | 1483 GenerateAddStrings(masm); |
1462 } | 1484 } |
1463 | 1485 |
1464 __ bind(&call_runtime); | 1486 __ bind(&call_runtime); |
1465 GenerateRegisterArgsPush(masm); | 1487 { |
1466 GenerateCallRuntime(masm); | 1488 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1489 GenerateRegisterArgsPush(masm); |
| 1490 GenerateCallRuntime(masm); |
| 1491 } |
| 1492 __ Ret(); |
1467 } | 1493 } |
1468 | 1494 |
1469 | 1495 |
1470 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, | 1496 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, |
1471 Label* alloc_failure, | 1497 Label* alloc_failure, |
1472 OverwriteMode mode) { | 1498 OverwriteMode mode) { |
1473 Label skip_allocation; | 1499 Label skip_allocation; |
1474 switch (mode) { | 1500 switch (mode) { |
1475 case OVERWRITE_LEFT: { | 1501 case OVERWRITE_LEFT: { |
1476 // If the argument in rdx is already an object, we skip the | 1502 // If the argument in rdx is already an object, we skip the |
(...skipping 23 matching lines...) Expand all Loading... |
1500 // now done and will not need it any more. | 1526 // now done and will not need it any more. |
1501 __ movq(rax, rbx); | 1527 __ movq(rax, rbx); |
1502 __ bind(&skip_allocation); | 1528 __ bind(&skip_allocation); |
1503 break; | 1529 break; |
1504 default: UNREACHABLE(); | 1530 default: UNREACHABLE(); |
1505 } | 1531 } |
1506 } | 1532 } |
1507 | 1533 |
1508 | 1534 |
1509 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { | 1535 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { |
1510 __ pop(rcx); | |
1511 __ push(rdx); | 1536 __ push(rdx); |
1512 __ push(rax); | 1537 __ push(rax); |
1513 __ push(rcx); | |
1514 } | 1538 } |
1515 | 1539 |
1516 | 1540 |
1517 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { | 1541 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { |
1518 // TAGGED case: | 1542 // TAGGED case: |
1519 // Input: | 1543 // Input: |
1520 // rsp[8]: argument (should be number). | 1544 // rsp[8]: argument (should be number). |
1521 // rsp[0]: return address. | 1545 // rsp[0]: return address. |
1522 // Output: | 1546 // Output: |
1523 // rax: tagged double result. | 1547 // rax: tagged double result. |
(...skipping 3260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4784 | 4808 |
4785 void StringAddStub::Generate(MacroAssembler* masm) { | 4809 void StringAddStub::Generate(MacroAssembler* masm) { |
4786 Label call_runtime, call_builtin; | 4810 Label call_runtime, call_builtin; |
4787 Builtins::JavaScript builtin_id = Builtins::ADD; | 4811 Builtins::JavaScript builtin_id = Builtins::ADD; |
4788 | 4812 |
4789 // Load the two arguments. | 4813 // Load the two arguments. |
4790 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument (left). | 4814 __ movq(rax, Operand(rsp, 2 * kPointerSize)); // First argument (left). |
4791 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right). | 4815 __ movq(rdx, Operand(rsp, 1 * kPointerSize)); // Second argument (right). |
4792 | 4816 |
4793 // Make sure that both arguments are strings if not known in advance. | 4817 // Make sure that both arguments are strings if not known in advance. |
4794 if (flags_ == NO_STRING_ADD_FLAGS) { | 4818 if ((flags_ & NO_STRING_ADD_FLAGS) != 0) { |
4795 __ JumpIfSmi(rax, &call_runtime); | 4819 __ JumpIfSmi(rax, &call_runtime); |
4796 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8); | 4820 __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, r8); |
4797 __ j(above_equal, &call_runtime); | 4821 __ j(above_equal, &call_runtime); |
4798 | 4822 |
4799 // First argument is a a string, test second. | 4823 // First argument is a a string, test second. |
4800 __ JumpIfSmi(rdx, &call_runtime); | 4824 __ JumpIfSmi(rdx, &call_runtime); |
4801 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9); | 4825 __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, r9); |
4802 __ j(above_equal, &call_runtime); | 4826 __ j(above_equal, &call_runtime); |
4803 } else { | 4827 } else { |
4804 // Here at least one of the arguments is definitely a string. | 4828 // Here at least one of the arguments is definitely a string. |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5061 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, false); | 5085 StringHelper::GenerateCopyCharacters(masm, rbx, rcx, r14, false); |
5062 // rbx: next character of result | 5086 // rbx: next character of result |
5063 // rdx: first char of second string | 5087 // rdx: first char of second string |
5064 // r15: length of second string | 5088 // r15: length of second string |
5065 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, false); | 5089 StringHelper::GenerateCopyCharacters(masm, rbx, rdx, r15, false); |
5066 __ IncrementCounter(counters->string_add_native(), 1); | 5090 __ IncrementCounter(counters->string_add_native(), 1); |
5067 __ ret(2 * kPointerSize); | 5091 __ ret(2 * kPointerSize); |
5068 | 5092 |
5069 // Just jump to runtime to add the two strings. | 5093 // Just jump to runtime to add the two strings. |
5070 __ bind(&call_runtime); | 5094 __ bind(&call_runtime); |
5071 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 5095 |
| 5096 if ((flags_ & ERECT_FRAME) != 0) { |
| 5097 GenerateRegisterArgsPop(masm, rcx); |
| 5098 // Build a frame |
| 5099 { |
| 5100 FrameScope scope(masm, StackFrame::INTERNAL); |
| 5101 GenerateRegisterArgsPush(masm); |
| 5102 __ CallRuntime(Runtime::kStringAdd, 2); |
| 5103 } |
| 5104 __ Ret(); |
| 5105 } else { |
| 5106 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
| 5107 } |
5072 | 5108 |
5073 if (call_builtin.is_linked()) { | 5109 if (call_builtin.is_linked()) { |
5074 __ bind(&call_builtin); | 5110 __ bind(&call_builtin); |
5075 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); | 5111 if ((flags_ & ERECT_FRAME) != 0) { |
| 5112 GenerateRegisterArgsPop(masm, rcx); |
| 5113 // Build a frame |
| 5114 { |
| 5115 FrameScope scope(masm, StackFrame::INTERNAL); |
| 5116 GenerateRegisterArgsPush(masm); |
| 5117 __ InvokeBuiltin(builtin_id, CALL_FUNCTION); |
| 5118 } |
| 5119 __ Ret(); |
| 5120 } else { |
| 5121 __ InvokeBuiltin(builtin_id, JUMP_FUNCTION); |
| 5122 } |
5076 } | 5123 } |
5077 } | 5124 } |
5078 | 5125 |
5079 | 5126 |
| 5127 void StringAddStub::GenerateRegisterArgsPush(MacroAssembler* masm) { |
| 5128 __ push(rax); |
| 5129 __ push(rdx); |
| 5130 } |
| 5131 |
| 5132 |
| 5133 void StringAddStub::GenerateRegisterArgsPop(MacroAssembler* masm, |
| 5134 Register temp) { |
| 5135 __ pop(temp); |
| 5136 __ pop(rdx); |
| 5137 __ pop(rax); |
| 5138 __ push(temp); |
| 5139 } |
| 5140 |
| 5141 |
5080 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, | 5142 void StringAddStub::GenerateConvertArgument(MacroAssembler* masm, |
5081 int stack_offset, | 5143 int stack_offset, |
5082 Register arg, | 5144 Register arg, |
5083 Register scratch1, | 5145 Register scratch1, |
5084 Register scratch2, | 5146 Register scratch2, |
5085 Register scratch3, | 5147 Register scratch3, |
5086 Label* slow) { | 5148 Label* slow) { |
5087 // First check if the argument is already a string. | 5149 // First check if the argument is already a string. |
5088 Label not_string, done; | 5150 Label not_string, done; |
5089 __ JumpIfSmi(arg, ¬_string); | 5151 __ JumpIfSmi(arg, ¬_string); |
(...skipping 1902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6992 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); | 7054 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); |
6993 } | 7055 } |
6994 } | 7056 } |
6995 | 7057 |
6996 | 7058 |
6997 #undef __ | 7059 #undef __ |
6998 | 7060 |
6999 } } // namespace v8::internal | 7061 } } // namespace v8::internal |
7000 | 7062 |
7001 #endif // V8_TARGET_ARCH_X64 | 7063 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |