OLD | NEW |
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 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1405 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1405 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
1406 | 1406 |
1407 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); | 1407 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
1408 // Avoid deopts in the case where we've never executed this path before. | 1408 // Avoid deopts in the case where we've never executed this path before. |
1409 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); | 1409 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
1410 | 1410 |
1411 if (expected.Contains(ToBooleanStub::UNDEFINED)) { | 1411 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
1412 // undefined -> false. | 1412 // undefined -> false. |
1413 __ cmp(reg, factory()->undefined_value()); | 1413 __ cmp(reg, factory()->undefined_value()); |
1414 __ j(equal, false_label); | 1414 __ j(equal, false_label); |
1415 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
1416 // We've seen undefined for the first time -> deopt. | |
1417 __ cmp(reg, factory()->undefined_value()); | |
1418 DeoptimizeIf(equal, instr->environment()); | |
1419 } | 1415 } |
1420 | |
1421 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | 1416 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
1422 // true -> true. | 1417 // true -> true. |
1423 __ cmp(reg, factory()->true_value()); | 1418 __ cmp(reg, factory()->true_value()); |
1424 __ j(equal, true_label); | 1419 __ j(equal, true_label); |
1425 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
1426 // We've seen a boolean for the first time -> deopt. | |
1427 __ cmp(reg, factory()->true_value()); | |
1428 DeoptimizeIf(equal, instr->environment()); | |
1429 } | |
1430 | |
1431 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | |
1432 // false -> false. | 1420 // false -> false. |
1433 __ cmp(reg, factory()->false_value()); | 1421 __ cmp(reg, factory()->false_value()); |
1434 __ j(equal, false_label); | 1422 __ j(equal, false_label); |
1435 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
1436 // We've seen a boolean for the first time -> deopt. | |
1437 __ cmp(reg, factory()->false_value()); | |
1438 DeoptimizeIf(equal, instr->environment()); | |
1439 } | 1423 } |
1440 | |
1441 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | 1424 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { |
1442 // 'null' -> false. | 1425 // 'null' -> false. |
1443 __ cmp(reg, factory()->null_value()); | 1426 __ cmp(reg, factory()->null_value()); |
1444 __ j(equal, false_label); | 1427 __ j(equal, false_label); |
1445 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
1446 // We've seen null for the first time -> deopt. | |
1447 __ cmp(reg, factory()->null_value()); | |
1448 DeoptimizeIf(equal, instr->environment()); | |
1449 } | 1428 } |
1450 | 1429 |
1451 if (expected.Contains(ToBooleanStub::SMI)) { | 1430 if (expected.Contains(ToBooleanStub::SMI)) { |
1452 // Smis: 0 -> false, all other -> true. | 1431 // Smis: 0 -> false, all other -> true. |
1453 __ test(reg, Operand(reg)); | 1432 __ test(reg, Operand(reg)); |
1454 __ j(equal, false_label); | 1433 __ j(equal, false_label); |
1455 __ JumpIfSmi(reg, true_label); | 1434 __ JumpIfSmi(reg, true_label); |
1456 } else if (expected.NeedsMap()) { | 1435 } else if (expected.NeedsMap()) { |
1457 // If we need a map later and have a Smi -> deopt. | 1436 // If we need a map later and have a Smi -> deopt. |
1458 __ test(reg, Immediate(kSmiTagMask)); | 1437 __ test(reg, Immediate(kSmiTagMask)); |
1459 DeoptimizeIf(zero, instr->environment()); | 1438 DeoptimizeIf(zero, instr->environment()); |
1460 } | 1439 } |
1461 | 1440 |
1462 Register map = no_reg; | 1441 Register map = no_reg; // Keep the compiler happy. |
1463 if (expected.NeedsMap()) { | 1442 if (expected.NeedsMap()) { |
1464 map = ToRegister(instr->TempAt(0)); | 1443 map = ToRegister(instr->TempAt(0)); |
1465 ASSERT(!map.is(reg)); | 1444 ASSERT(!map.is(reg)); |
1466 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 1445 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
1467 // Everything with a map could be undetectable, so check this now. | 1446 |
1468 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | 1447 if (expected.CanBeUndetectable()) { |
1469 1 << Map::kIsUndetectable); | 1448 // Undetectable -> false. |
1470 // Undetectable -> false. | 1449 __ test_b(FieldOperand(map, Map::kBitFieldOffset), |
1471 __ j(not_zero, false_label); | 1450 1 << Map::kIsUndetectable); |
| 1451 __ j(not_zero, false_label); |
| 1452 } |
1472 } | 1453 } |
1473 | 1454 |
1474 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | 1455 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { |
1475 // spec object -> true. | 1456 // spec object -> true. |
1476 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | 1457 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); |
1477 __ j(above_equal, true_label); | 1458 __ j(above_equal, true_label); |
1478 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
1479 // We've seen a spec object for the first time -> deopt. | |
1480 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | |
1481 DeoptimizeIf(above_equal, instr->environment()); | |
1482 } | 1459 } |
1483 | 1460 |
1484 if (expected.Contains(ToBooleanStub::STRING)) { | 1461 if (expected.Contains(ToBooleanStub::STRING)) { |
1485 // String value -> false iff empty. | 1462 // String value -> false iff empty. |
1486 Label not_string; | 1463 Label not_string; |
1487 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | 1464 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); |
1488 __ j(above_equal, ¬_string, Label::kNear); | 1465 __ j(above_equal, ¬_string, Label::kNear); |
1489 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | 1466 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); |
1490 __ j(not_zero, true_label); | 1467 __ j(not_zero, true_label); |
1491 __ jmp(false_label); | 1468 __ jmp(false_label); |
1492 __ bind(¬_string); | 1469 __ bind(¬_string); |
1493 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
1494 // We've seen a string for the first time -> deopt | |
1495 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | |
1496 DeoptimizeIf(below, instr->environment()); | |
1497 } | 1470 } |
1498 | 1471 |
1499 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | 1472 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { |
1500 // heap number -> false iff +0, -0, or NaN. | 1473 // heap number -> false iff +0, -0, or NaN. |
1501 Label not_heap_number; | 1474 Label not_heap_number; |
1502 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1475 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
1503 factory()->heap_number_map()); | 1476 factory()->heap_number_map()); |
1504 __ j(not_equal, ¬_heap_number, Label::kNear); | 1477 __ j(not_equal, ¬_heap_number, Label::kNear); |
1505 __ fldz(); | 1478 __ fldz(); |
1506 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 1479 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
1507 __ FCmp(); | 1480 __ FCmp(); |
1508 __ j(zero, false_label); | 1481 __ j(zero, false_label); |
1509 __ jmp(true_label); | 1482 __ jmp(true_label); |
1510 __ bind(¬_heap_number); | 1483 __ bind(¬_heap_number); |
1511 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
1512 // We've seen a heap number for the first time -> deopt. | |
1513 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | |
1514 factory()->heap_number_map()); | |
1515 DeoptimizeIf(equal, instr->environment()); | |
1516 } | 1484 } |
1517 | 1485 |
1518 if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | 1486 // We've seen something for the first time -> deopt. |
1519 // internal objects -> true | 1487 DeoptimizeIf(no_condition, instr->environment()); |
1520 __ jmp(true_label); | |
1521 } else { | |
1522 // We've seen something for the first time -> deopt. | |
1523 DeoptimizeIf(no_condition, instr->environment()); | |
1524 } | |
1525 } | 1488 } |
1526 } | 1489 } |
1527 } | 1490 } |
1528 | 1491 |
1529 | 1492 |
1530 void LCodeGen::EmitGoto(int block) { | 1493 void LCodeGen::EmitGoto(int block) { |
1531 block = chunk_->LookupDestination(block); | 1494 block = chunk_->LookupDestination(block); |
1532 int next_block = GetNextEmittedBlock(current_block_); | 1495 int next_block = GetNextEmittedBlock(current_block_); |
1533 if (block != next_block) { | 1496 if (block != next_block) { |
1534 __ jmp(chunk_->GetAssemblyLabel(block)); | 1497 __ jmp(chunk_->GetAssemblyLabel(block)); |
(...skipping 2864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4399 env->deoptimization_index()); | 4362 env->deoptimization_index()); |
4400 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4363 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
4401 } | 4364 } |
4402 | 4365 |
4403 | 4366 |
4404 #undef __ | 4367 #undef __ |
4405 | 4368 |
4406 } } // namespace v8::internal | 4369 } } // namespace v8::internal |
4407 | 4370 |
4408 #endif // V8_TARGET_ARCH_IA32 | 4371 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |