| 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 |