| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1322 ASSERT(right_side.is_valid()); | 1322 ASSERT(right_side.is_valid()); |
| 1323 __ cmp(left_side.reg(), Operand(right_side.reg())); | 1323 __ cmp(left_side.reg(), Operand(right_side.reg())); |
| 1324 } else { | 1324 } else { |
| 1325 __ cmp(Operand(left_side.reg()), Immediate(right_side.handle())); | 1325 __ cmp(Operand(left_side.reg()), Immediate(right_side.handle())); |
| 1326 } | 1326 } |
| 1327 left_side.Unuse(); | 1327 left_side.Unuse(); |
| 1328 right_side.Unuse(); | 1328 right_side.Unuse(); |
| 1329 dest->Split(cc); | 1329 dest->Split(cc); |
| 1330 } | 1330 } |
| 1331 } else { // Neither side is a constant Smi, normal comparison operation. | 1331 } else { // Neither side is a constant Smi, normal comparison operation. |
| 1332 // If either side is a non-smi constant, skip the smi check. |
| 1333 bool known_non_smi = |
| 1334 left_side.is_constant() && !left_side.handle()->IsSmi() || |
| 1335 right_side.is_constant() && !right_side.handle()->IsSmi(); |
| 1332 left_side.ToRegister(); | 1336 left_side.ToRegister(); |
| 1333 right_side.ToRegister(); | 1337 right_side.ToRegister(); |
| 1334 ASSERT(left_side.is_valid()); | |
| 1335 ASSERT(right_side.is_valid()); | |
| 1336 // Check for the smi case. | |
| 1337 JumpTarget is_smi(this); | 1338 JumpTarget is_smi(this); |
| 1338 Result temp = allocator_->Allocate(); | 1339 if (!known_non_smi) { |
| 1339 ASSERT(temp.is_valid()); | 1340 // Check for the smi case. |
| 1340 __ mov(temp.reg(), left_side.reg()); | 1341 Result temp = allocator_->Allocate(); |
| 1341 __ or_(temp.reg(), Operand(right_side.reg())); | 1342 ASSERT(temp.is_valid()); |
| 1342 __ test(temp.reg(), Immediate(kSmiTagMask)); | 1343 __ mov(temp.reg(), left_side.reg()); |
| 1343 temp.Unuse(); | 1344 __ or_(temp.reg(), Operand(right_side.reg())); |
| 1344 is_smi.Branch(zero, &left_side, &right_side, taken); | 1345 __ test(temp.reg(), Immediate(kSmiTagMask)); |
| 1345 | 1346 temp.Unuse(); |
| 1347 is_smi.Branch(zero, &left_side, &right_side, taken); |
| 1348 } |
| 1346 // When non-smi, call out to the compare stub. "parameters" setup by | 1349 // When non-smi, call out to the compare stub. "parameters" setup by |
| 1347 // calling code in edx and eax and "result" is returned in the flags. | 1350 // calling code in edx and eax and "result" is returned in the flags. |
| 1348 if (!left_side.reg().is(eax)) { | 1351 if (!left_side.reg().is(eax)) { |
| 1349 right_side.ToRegister(eax); | 1352 right_side.ToRegister(eax); |
| 1350 left_side.ToRegister(edx); | 1353 left_side.ToRegister(edx); |
| 1351 } else if (!right_side.reg().is(edx)) { | 1354 } else if (!right_side.reg().is(edx)) { |
| 1352 left_side.ToRegister(edx); | 1355 left_side.ToRegister(edx); |
| 1353 right_side.ToRegister(eax); | 1356 right_side.ToRegister(eax); |
| 1354 } else { | 1357 } else { |
| 1355 frame_->Spill(eax); // Can be multiply referenced, even now. | 1358 frame_->Spill(eax); // Can be multiply referenced, even now. |
| 1356 frame_->Spill(edx); | 1359 frame_->Spill(edx); |
| 1357 __ xchg(eax, edx); | 1360 __ xchg(eax, edx); |
| 1358 // If left_side and right_side become real (non-dummy) arguments | 1361 // If left_side and right_side become real (non-dummy) arguments |
| 1359 // to CallStub, they need to be swapped in this case. | 1362 // to CallStub, they need to be swapped in this case. |
| 1360 } | 1363 } |
| 1361 CompareStub stub(cc, strict); | 1364 CompareStub stub(cc, strict); |
| 1362 Result answer = frame_->CallStub(&stub, &right_side, &left_side, 0); | 1365 Result answer = frame_->CallStub(&stub, &right_side, &left_side, 0); |
| 1363 if (cc == equal) { | 1366 if (cc == equal) { |
| 1364 __ test(answer.reg(), Operand(answer.reg())); | 1367 __ test(answer.reg(), Operand(answer.reg())); |
| 1365 } else { | 1368 } else { |
| 1366 __ cmp(answer.reg(), 0); | 1369 __ cmp(answer.reg(), 0); |
| 1367 } | 1370 } |
| 1368 answer.Unuse(); | 1371 answer.Unuse(); |
| 1369 dest->true_target()->Branch(cc); | 1372 if (known_non_smi) { |
| 1370 dest->false_target()->Jump(); | 1373 dest->Split(cc); |
| 1371 | 1374 } else { |
| 1372 is_smi.Bind(&left_side, &right_side); | 1375 dest->true_target()->Branch(cc); |
| 1373 left_side.ToRegister(); | 1376 dest->false_target()->Jump(); |
| 1374 right_side.ToRegister(); | 1377 is_smi.Bind(&left_side, &right_side); |
| 1375 __ cmp(left_side.reg(), Operand(right_side.reg())); | 1378 left_side.ToRegister(); |
| 1376 right_side.Unuse(); | 1379 right_side.ToRegister(); |
| 1377 left_side.Unuse(); | 1380 __ cmp(left_side.reg(), Operand(right_side.reg())); |
| 1378 dest->Split(cc); | 1381 right_side.Unuse(); |
| 1382 left_side.Unuse(); |
| 1383 dest->Split(cc); |
| 1384 } |
| 1379 } | 1385 } |
| 1380 } | 1386 } |
| 1381 | 1387 |
| 1382 | 1388 |
| 1383 void CodeGenerator::SmiComparison(Condition cc, | |
| 1384 Handle<Object> smi_value, | |
| 1385 bool strict) { | |
| 1386 // Strict only makes sense for equality comparisons. | |
| 1387 ASSERT(!strict || cc == equal); | |
| 1388 ASSERT(is_intn(Smi::cast(*smi_value)->value(), kMaxSmiInlinedBits)); | |
| 1389 | |
| 1390 JumpTarget is_smi(this); | |
| 1391 Result comparee = frame_->Pop(); | |
| 1392 comparee.ToRegister(); | |
| 1393 // Check whether the other operand is a smi. | |
| 1394 __ test(comparee.reg(), Immediate(kSmiTagMask)); | |
| 1395 is_smi.Branch(zero, &comparee, taken); | |
| 1396 | |
| 1397 // Setup and call the compare stub, which expects arguments in edx | |
| 1398 // and eax. | |
| 1399 CompareStub stub(cc, strict); | |
| 1400 comparee.ToRegister(edx); | |
| 1401 Result value = allocator_->Allocate(eax); | |
| 1402 ASSERT(value.is_valid()); | |
| 1403 __ Set(value.reg(), Immediate(smi_value)); | |
| 1404 Result result = frame_->CallStub(&stub, &comparee, &value, 0); | |
| 1405 __ cmp(result.reg(), 0); | |
| 1406 result.Unuse(); | |
| 1407 destination()->true_target()->Branch(cc); | |
| 1408 destination()->false_target()->Jump(); | |
| 1409 | |
| 1410 is_smi.Bind(&comparee); | |
| 1411 comparee.ToRegister(); | |
| 1412 // Test smi equality and comparison by signed int comparison. | |
| 1413 __ cmp(Operand(comparee.reg()), Immediate(smi_value)); | |
| 1414 comparee.Unuse(); | |
| 1415 destination()->Split(cc); | |
| 1416 } | |
| 1417 | |
| 1418 | |
| 1419 class CallFunctionStub: public CodeStub { | 1389 class CallFunctionStub: public CodeStub { |
| 1420 public: | 1390 public: |
| 1421 explicit CallFunctionStub(int argc) : argc_(argc) { } | 1391 explicit CallFunctionStub(int argc) : argc_(argc) { } |
| 1422 | 1392 |
| 1423 void Generate(MacroAssembler* masm); | 1393 void Generate(MacroAssembler* masm); |
| 1424 | 1394 |
| 1425 private: | 1395 private: |
| 1426 int argc_; | 1396 int argc_; |
| 1427 | 1397 |
| 1428 #ifdef DEBUG | 1398 #ifdef DEBUG |
| (...skipping 3306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4735 Result answer = frame_->CallStub(&stub, 2); | 4705 Result answer = frame_->CallStub(&stub, 2); |
| 4736 answer.ToRegister(); | 4706 answer.ToRegister(); |
| 4737 __ test(answer.reg(), Operand(answer.reg())); | 4707 __ test(answer.reg(), Operand(answer.reg())); |
| 4738 answer.Unuse(); | 4708 answer.Unuse(); |
| 4739 destination()->Split(zero); | 4709 destination()->Split(zero); |
| 4740 return; | 4710 return; |
| 4741 } | 4711 } |
| 4742 default: | 4712 default: |
| 4743 UNREACHABLE(); | 4713 UNREACHABLE(); |
| 4744 } | 4714 } |
| 4745 | 4715 Load(left); |
| 4746 // Optimize for the case where (at least) one of the expressions | 4716 Load(right); |
| 4747 // is a literal small integer. | 4717 Comparison(cc, strict, destination()); |
| 4748 if (IsInlineSmi(left->AsLiteral())) { | |
| 4749 Load(right); | |
| 4750 SmiComparison(ReverseCondition(cc), left->AsLiteral()->handle(), strict); | |
| 4751 } else if (IsInlineSmi(right->AsLiteral())) { | |
| 4752 Load(left); | |
| 4753 SmiComparison(cc, right->AsLiteral()->handle(), strict); | |
| 4754 } else { | |
| 4755 Load(left); | |
| 4756 Load(right); | |
| 4757 Comparison(cc, strict, destination()); | |
| 4758 } | |
| 4759 } | 4718 } |
| 4760 | 4719 |
| 4761 | 4720 |
| 4762 #ifdef DEBUG | 4721 #ifdef DEBUG |
| 4763 bool CodeGenerator::HasValidEntryRegisters() { | 4722 bool CodeGenerator::HasValidEntryRegisters() { |
| 4764 return (allocator()->count(eax) == frame()->register_count(eax)) | 4723 return (allocator()->count(eax) == frame()->register_count(eax)) |
| 4765 && (allocator()->count(ebx) == frame()->register_count(ebx)) | 4724 && (allocator()->count(ebx) == frame()->register_count(ebx)) |
| 4766 && (allocator()->count(ecx) == frame()->register_count(ecx)) | 4725 && (allocator()->count(ecx) == frame()->register_count(ecx)) |
| 4767 && (allocator()->count(edx) == frame()->register_count(edx)) | 4726 && (allocator()->count(edx) == frame()->register_count(edx)) |
| 4768 && (allocator()->count(edi) == frame()->register_count(edi)); | 4727 && (allocator()->count(edi) == frame()->register_count(edi)); |
| (...skipping 1798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6567 | 6526 |
| 6568 // Slow-case: Go through the JavaScript implementation. | 6527 // Slow-case: Go through the JavaScript implementation. |
| 6569 __ bind(&slow); | 6528 __ bind(&slow); |
| 6570 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6529 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6571 } | 6530 } |
| 6572 | 6531 |
| 6573 | 6532 |
| 6574 #undef __ | 6533 #undef __ |
| 6575 | 6534 |
| 6576 } } // namespace v8::internal | 6535 } } // namespace v8::internal |
| OLD | NEW |