Chromium Code Reviews| 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 1374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1385 Register reg = ToRegister(instr->InputAt(0)); | 1385 Register reg = ToRegister(instr->InputAt(0)); |
| 1386 __ test(reg, Operand(reg)); | 1386 __ test(reg, Operand(reg)); |
| 1387 EmitBranch(true_block, false_block, not_zero); | 1387 EmitBranch(true_block, false_block, not_zero); |
| 1388 } else if (r.IsDouble()) { | 1388 } else if (r.IsDouble()) { |
| 1389 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1389 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); |
| 1390 __ xorps(xmm0, xmm0); | 1390 __ xorps(xmm0, xmm0); |
| 1391 __ ucomisd(reg, xmm0); | 1391 __ ucomisd(reg, xmm0); |
| 1392 EmitBranch(true_block, false_block, not_equal); | 1392 EmitBranch(true_block, false_block, not_equal); |
| 1393 } else { | 1393 } else { |
| 1394 ASSERT(r.IsTagged()); | 1394 ASSERT(r.IsTagged()); |
| 1395 Factory* factory = this->factory(); | |
|
fschneider
2011/07/28 13:54:58
Doesn't the compiler inline the factory() accessor
Sven Panne
2011/07/28 14:12:44
Ooops, I haven't seen that retrieving the current
| |
| 1395 Register reg = ToRegister(instr->InputAt(0)); | 1396 Register reg = ToRegister(instr->InputAt(0)); |
| 1396 if (instr->hydrogen()->value()->type().IsBoolean()) { | 1397 if (instr->hydrogen()->value()->type().IsBoolean()) { |
| 1397 __ cmp(reg, factory()->true_value()); | 1398 __ cmp(reg, factory->true_value()); |
| 1398 EmitBranch(true_block, false_block, equal); | 1399 EmitBranch(true_block, false_block, equal); |
| 1399 } else { | 1400 } else { |
| 1400 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1401 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1401 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1402 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1402 | 1403 |
| 1403 __ cmp(reg, factory()->undefined_value()); | 1404 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); |
| 1404 __ j(equal, false_label); | 1405 // Avoid deopts in the case where we've never executed this path before. |
| 1405 __ cmp(reg, factory()->true_value()); | 1406 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); |
|
fschneider
2011/07/28 13:54:58
We should watch out for code size a little. If thi
Sven Panne
2011/07/28 14:12:44
In the programs I've seen so far this doesn't happ
| |
| 1406 __ j(equal, true_label); | |
| 1407 __ cmp(reg, factory()->false_value()); | |
| 1408 __ j(equal, false_label); | |
| 1409 __ test(reg, Operand(reg)); | |
| 1410 __ j(equal, false_label); | |
| 1411 __ JumpIfSmi(reg, true_label); | |
| 1412 | 1407 |
| 1413 // Test for double values. Zero is false. | 1408 if (expected.Contains(ToBooleanStub::UNDEFINED)) { |
| 1414 Label call_stub; | 1409 // undefined -> false. |
| 1415 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1410 __ cmp(reg, factory->undefined_value()); |
| 1416 factory()->heap_number_map()); | 1411 __ j(equal, false_label); |
| 1417 __ j(not_equal, &call_stub, Label::kNear); | 1412 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { |
| 1418 __ fldz(); | 1413 // We've seen undefined for the first time -> deopt. |
| 1419 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 1414 __ cmp(reg, factory->undefined_value()); |
| 1420 __ FCmp(); | 1415 DeoptimizeIf(equal, instr->environment()); |
| 1421 __ j(zero, false_label); | 1416 } |
| 1422 __ jmp(true_label); | |
| 1423 | 1417 |
| 1424 // The conversion stub doesn't cause garbage collections so it's | 1418 if (expected.Contains(ToBooleanStub::BOOLEAN)) { |
| 1425 // safe to not record a safepoint after the call. | 1419 // true -> true. |
| 1426 __ bind(&call_stub); | 1420 __ cmp(reg, factory->true_value()); |
| 1427 ToBooleanStub stub(eax, ToBooleanStub::all_types()); | 1421 __ j(equal, true_label); |
| 1428 __ pushad(); | 1422 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { |
| 1429 __ push(reg); | 1423 // We've seen a string for the first time -> deopt. |
|
fschneider
2011/07/28 13:54:58
Update comment: s/string/boolean
Sven Panne
2011/07/28 14:12:44
Done.
| |
| 1430 __ CallStub(&stub); | 1424 __ cmp(reg, factory->true_value()); |
| 1431 __ test(eax, Operand(eax)); | 1425 DeoptimizeIf(equal, instr->environment()); |
| 1432 __ popad(); | 1426 } |
| 1433 EmitBranch(true_block, false_block, not_zero); | 1427 |
| 1428 if (expected.Contains(ToBooleanStub::BOOLEAN)) { | |
| 1429 // false -> false. | |
| 1430 __ cmp(reg, factory->false_value()); | |
| 1431 __ j(equal, false_label); | |
| 1432 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1433 // We've seen a string for the first time -> deopt. | |
|
fschneider
2011/07/28 13:54:58
Same here.
Sven Panne
2011/07/28 14:12:44
Done.
| |
| 1434 __ cmp(reg, factory->false_value()); | |
| 1435 DeoptimizeIf(equal, instr->environment()); | |
| 1436 } | |
| 1437 | |
| 1438 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { | |
| 1439 // 'null' -> false. | |
| 1440 __ cmp(reg, factory->null_value()); | |
| 1441 __ j(equal, false_label); | |
| 1442 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1443 // We've seen null for the first time -> deopt. | |
| 1444 __ cmp(reg, factory->null_value()); | |
| 1445 DeoptimizeIf(equal, instr->environment()); | |
| 1446 } | |
| 1447 | |
| 1448 if (expected.Contains(ToBooleanStub::SMI)) { | |
| 1449 // Smis: 0 -> false, all other -> true. | |
| 1450 __ test(reg, Operand(reg)); | |
| 1451 __ j(equal, false_label); | |
| 1452 __ JumpIfSmi(reg, true_label); | |
| 1453 } else if (expected.NeedsMap()) { | |
| 1454 // If we need a map later and have a Smi -> deopt. | |
| 1455 __ test(reg, Immediate(kSmiTagMask)); | |
| 1456 DeoptimizeIf(zero, instr->environment()); | |
| 1457 } | |
| 1458 | |
| 1459 Register map; | |
| 1460 if (expected.NeedsMap()) { | |
| 1461 map = ToRegister(instr->TempAt(0)); | |
| 1462 ASSERT(!map.is(reg)); | |
| 1463 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | |
| 1464 // Everything with a map could be undetectable, so check this now. | |
| 1465 __ test_b(FieldOperand(map, Map::kBitFieldOffset), | |
| 1466 1 << Map::kIsUndetectable); | |
| 1467 // Undetectable -> false. | |
| 1468 __ j(not_zero, false_label); | |
| 1469 } | |
| 1470 | |
| 1471 if (expected.Contains(ToBooleanStub::SPEC_OBJECT)) { | |
| 1472 // spec object -> true. | |
| 1473 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | |
| 1474 __ j(above_equal, true_label); | |
| 1475 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1476 // We've seen a spec object for the first time -> deopt. | |
| 1477 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); | |
| 1478 DeoptimizeIf(above_equal, instr->environment()); | |
| 1479 } | |
| 1480 | |
| 1481 if (expected.Contains(ToBooleanStub::STRING)) { | |
| 1482 // String value -> false iff empty. | |
| 1483 Label not_string; | |
| 1484 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | |
| 1485 __ j(above_equal, ¬_string, Label::kNear); | |
| 1486 __ cmp(FieldOperand(reg, String::kLengthOffset), Immediate(0)); | |
| 1487 __ j(not_zero, true_label); | |
| 1488 __ jmp(false_label); | |
| 1489 __ bind(¬_string); | |
| 1490 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1491 // We've seen a string for the first time -> deopt | |
| 1492 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); | |
| 1493 DeoptimizeIf(below, instr->environment()); | |
| 1494 } | |
| 1495 | |
| 1496 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { | |
| 1497 // heap number -> false iff +0, -0, or NaN. | |
| 1498 Label not_heap_number; | |
| 1499 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | |
| 1500 factory->heap_number_map()); | |
| 1501 __ j(not_equal, ¬_heap_number, Label::kNear); | |
| 1502 __ fldz(); | |
| 1503 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | |
| 1504 __ FCmp(); | |
| 1505 __ j(zero, false_label); | |
| 1506 __ jmp(true_label); | |
| 1507 __ bind(¬_heap_number); | |
| 1508 } else if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1509 // We've seen a heap number for the first time -> deopt. | |
| 1510 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | |
| 1511 factory->heap_number_map()); | |
| 1512 DeoptimizeIf(equal, instr->environment()); | |
| 1513 } | |
| 1514 | |
| 1515 if (expected.Contains(ToBooleanStub::INTERNAL_OBJECT)) { | |
| 1516 // internal objects -> true | |
| 1517 __ jmp(true_label); | |
| 1518 } else { | |
| 1519 // We've seen something for the first time -> deopt. | |
| 1520 DeoptimizeIf(no_condition, instr->environment()); | |
| 1521 } | |
| 1434 } | 1522 } |
| 1435 } | 1523 } |
| 1436 } | 1524 } |
| 1437 | 1525 |
| 1438 | 1526 |
| 1439 void LCodeGen::EmitGoto(int block) { | 1527 void LCodeGen::EmitGoto(int block) { |
| 1440 block = chunk_->LookupDestination(block); | 1528 block = chunk_->LookupDestination(block); |
| 1441 int next_block = GetNextEmittedBlock(current_block_); | 1529 int next_block = GetNextEmittedBlock(current_block_); |
| 1442 if (block != next_block) { | 1530 if (block != next_block) { |
| 1443 __ jmp(chunk_->GetAssemblyLabel(block)); | 1531 __ jmp(chunk_->GetAssemblyLabel(block)); |
| (...skipping 2864 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4308 env->deoptimization_index()); | 4396 env->deoptimization_index()); |
| 4309 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4397 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4310 } | 4398 } |
| 4311 | 4399 |
| 4312 | 4400 |
| 4313 #undef __ | 4401 #undef __ |
| 4314 | 4402 |
| 4315 } } // namespace v8::internal | 4403 } } // namespace v8::internal |
| 4316 | 4404 |
| 4317 #endif // V8_TARGET_ARCH_IA32 | 4405 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |