| 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 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 | 459 |
| 460 // Signal that we don't inline smi code before these stubs in the | 460 // Signal that we don't inline smi code before these stubs in the |
| 461 // optimizing code generator. | 461 // optimizing code generator. |
| 462 if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC || | 462 if (code->kind() == Code::TYPE_RECORDING_BINARY_OP_IC || |
| 463 code->kind() == Code::COMPARE_IC) { | 463 code->kind() == Code::COMPARE_IC) { |
| 464 __ nop(); | 464 __ nop(); |
| 465 } | 465 } |
| 466 } | 466 } |
| 467 | 467 |
| 468 | 468 |
| 469 void LCodeGen::CallRuntime(Runtime::Function* fun, | 469 void LCodeGen::CallRuntime(const Runtime::Function* fun, |
| 470 int argc, | 470 int argc, |
| 471 LInstruction* instr, | 471 LInstruction* instr, |
| 472 bool adjusted) { | 472 bool adjusted) { |
| 473 ASSERT(instr != NULL); | 473 ASSERT(instr != NULL); |
| 474 ASSERT(instr->HasPointerMap()); | 474 ASSERT(instr->HasPointerMap()); |
| 475 LPointerMap* pointers = instr->pointer_map(); | 475 LPointerMap* pointers = instr->pointer_map(); |
| 476 RecordPosition(pointers->position()); | 476 RecordPosition(pointers->position()); |
| 477 | 477 |
| 478 if (!adjusted) { | 478 if (!adjusted) { |
| 479 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 479 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 } | 579 } |
| 580 } | 580 } |
| 581 } | 581 } |
| 582 | 582 |
| 583 | 583 |
| 584 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 584 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 585 int length = deoptimizations_.length(); | 585 int length = deoptimizations_.length(); |
| 586 if (length == 0) return; | 586 if (length == 0) return; |
| 587 ASSERT(FLAG_deopt); | 587 ASSERT(FLAG_deopt); |
| 588 Handle<DeoptimizationInputData> data = | 588 Handle<DeoptimizationInputData> data = |
| 589 Factory::NewDeoptimizationInputData(length, TENURED); | 589 factory()->NewDeoptimizationInputData(length, TENURED); |
| 590 | 590 |
| 591 Handle<ByteArray> translations = translations_.CreateByteArray(); | 591 Handle<ByteArray> translations = translations_.CreateByteArray(); |
| 592 data->SetTranslationByteArray(*translations); | 592 data->SetTranslationByteArray(*translations); |
| 593 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); | 593 data->SetInlinedFunctionCount(Smi::FromInt(inlined_function_count_)); |
| 594 | 594 |
| 595 Handle<FixedArray> literals = | 595 Handle<FixedArray> literals = |
| 596 Factory::NewFixedArray(deoptimization_literals_.length(), TENURED); | 596 factory()->NewFixedArray(deoptimization_literals_.length(), TENURED); |
| 597 for (int i = 0; i < deoptimization_literals_.length(); i++) { | 597 for (int i = 0; i < deoptimization_literals_.length(); i++) { |
| 598 literals->set(i, *deoptimization_literals_[i]); | 598 literals->set(i, *deoptimization_literals_[i]); |
| 599 } | 599 } |
| 600 data->SetLiteralArray(*literals); | 600 data->SetLiteralArray(*literals); |
| 601 | 601 |
| 602 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); | 602 data->SetOsrAstId(Smi::FromInt(info_->osr_ast_id())); |
| 603 data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); | 603 data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); |
| 604 | 604 |
| 605 // Populate the deoptimization entries. | 605 // Populate the deoptimization entries. |
| 606 for (int i = 0; i < length; i++) { | 606 for (int i = 0; i < length; i++) { |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1088 double v = instr->value(); | 1088 double v = instr->value(); |
| 1089 // Use xor to produce +0.0 in a fast and compact way, but avoid to | 1089 // Use xor to produce +0.0 in a fast and compact way, but avoid to |
| 1090 // do so if the constant is -0.0. | 1090 // do so if the constant is -0.0. |
| 1091 if (BitCast<uint64_t, double>(v) == 0) { | 1091 if (BitCast<uint64_t, double>(v) == 0) { |
| 1092 __ xorpd(res, res); | 1092 __ xorpd(res, res); |
| 1093 } else { | 1093 } else { |
| 1094 Register temp = ToRegister(instr->TempAt(0)); | 1094 Register temp = ToRegister(instr->TempAt(0)); |
| 1095 uint64_t int_val = BitCast<uint64_t, double>(v); | 1095 uint64_t int_val = BitCast<uint64_t, double>(v); |
| 1096 int32_t lower = static_cast<int32_t>(int_val); | 1096 int32_t lower = static_cast<int32_t>(int_val); |
| 1097 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | 1097 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); |
| 1098 if (CpuFeatures::IsSupported(SSE4_1)) { | 1098 if (isolate()->cpu_features()->IsSupported(SSE4_1)) { |
| 1099 CpuFeatures::Scope scope(SSE4_1); | 1099 CpuFeatures::Scope scope(SSE4_1); |
| 1100 if (lower != 0) { | 1100 if (lower != 0) { |
| 1101 __ Set(temp, Immediate(lower)); | 1101 __ Set(temp, Immediate(lower)); |
| 1102 __ movd(res, Operand(temp)); | 1102 __ movd(res, Operand(temp)); |
| 1103 __ Set(temp, Immediate(upper)); | 1103 __ Set(temp, Immediate(upper)); |
| 1104 __ pinsrd(res, Operand(temp), 1); | 1104 __ pinsrd(res, Operand(temp), 1); |
| 1105 } else { | 1105 } else { |
| 1106 __ xorpd(res, res); | 1106 __ xorpd(res, res); |
| 1107 __ Set(temp, Immediate(upper)); | 1107 __ Set(temp, Immediate(upper)); |
| 1108 __ pinsrd(res, Operand(temp), 1); | 1108 __ pinsrd(res, Operand(temp), 1); |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1291 EmitBranch(true_block, false_block, not_zero); | 1291 EmitBranch(true_block, false_block, not_zero); |
| 1292 } else if (r.IsDouble()) { | 1292 } else if (r.IsDouble()) { |
| 1293 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); | 1293 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); |
| 1294 __ xorpd(xmm0, xmm0); | 1294 __ xorpd(xmm0, xmm0); |
| 1295 __ ucomisd(reg, xmm0); | 1295 __ ucomisd(reg, xmm0); |
| 1296 EmitBranch(true_block, false_block, not_equal); | 1296 EmitBranch(true_block, false_block, not_equal); |
| 1297 } else { | 1297 } else { |
| 1298 ASSERT(r.IsTagged()); | 1298 ASSERT(r.IsTagged()); |
| 1299 Register reg = ToRegister(instr->InputAt(0)); | 1299 Register reg = ToRegister(instr->InputAt(0)); |
| 1300 if (instr->hydrogen()->type().IsBoolean()) { | 1300 if (instr->hydrogen()->type().IsBoolean()) { |
| 1301 __ cmp(reg, Factory::true_value()); | 1301 __ cmp(reg, factory()->true_value()); |
| 1302 EmitBranch(true_block, false_block, equal); | 1302 EmitBranch(true_block, false_block, equal); |
| 1303 } else { | 1303 } else { |
| 1304 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1304 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1305 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1305 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1306 | 1306 |
| 1307 __ cmp(reg, Factory::undefined_value()); | 1307 __ cmp(reg, factory()->undefined_value()); |
| 1308 __ j(equal, false_label); | 1308 __ j(equal, false_label); |
| 1309 __ cmp(reg, Factory::true_value()); | 1309 __ cmp(reg, factory()->true_value()); |
| 1310 __ j(equal, true_label); | 1310 __ j(equal, true_label); |
| 1311 __ cmp(reg, Factory::false_value()); | 1311 __ cmp(reg, factory()->false_value()); |
| 1312 __ j(equal, false_label); | 1312 __ j(equal, false_label); |
| 1313 __ test(reg, Operand(reg)); | 1313 __ test(reg, Operand(reg)); |
| 1314 __ j(equal, false_label); | 1314 __ j(equal, false_label); |
| 1315 __ test(reg, Immediate(kSmiTagMask)); | 1315 __ test(reg, Immediate(kSmiTagMask)); |
| 1316 __ j(zero, true_label); | 1316 __ j(zero, true_label); |
| 1317 | 1317 |
| 1318 // Test for double values. Zero is false. | 1318 // Test for double values. Zero is false. |
| 1319 NearLabel call_stub; | 1319 NearLabel call_stub; |
| 1320 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1320 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 1321 Factory::heap_number_map()); | 1321 factory()->heap_number_map()); |
| 1322 __ j(not_equal, &call_stub); | 1322 __ j(not_equal, &call_stub); |
| 1323 __ fldz(); | 1323 __ fldz(); |
| 1324 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); | 1324 __ fld_d(FieldOperand(reg, HeapNumber::kValueOffset)); |
| 1325 __ FCmp(); | 1325 __ FCmp(); |
| 1326 __ j(zero, false_label); | 1326 __ j(zero, false_label); |
| 1327 __ jmp(true_label); | 1327 __ jmp(true_label); |
| 1328 | 1328 |
| 1329 // The conversion stub doesn't cause garbage collections so it's | 1329 // The conversion stub doesn't cause garbage collections so it's |
| 1330 // safe to not record a safepoint after the call. | 1330 // safe to not record a safepoint after the call. |
| 1331 __ bind(&call_stub); | 1331 __ bind(&call_stub); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1434 // Don't base result on EFLAGS when a NaN is involved. Instead | 1434 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 1435 // jump to the unordered case, which produces a false value. | 1435 // jump to the unordered case, which produces a false value. |
| 1436 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1436 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 1437 __ j(parity_even, &unordered, not_taken); | 1437 __ j(parity_even, &unordered, not_taken); |
| 1438 } else { | 1438 } else { |
| 1439 EmitCmpI(left, right); | 1439 EmitCmpI(left, right); |
| 1440 } | 1440 } |
| 1441 | 1441 |
| 1442 NearLabel done; | 1442 NearLabel done; |
| 1443 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1443 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
| 1444 __ mov(ToRegister(result), Factory::true_value()); | 1444 __ mov(ToRegister(result), factory()->true_value()); |
| 1445 __ j(cc, &done); | 1445 __ j(cc, &done); |
| 1446 | 1446 |
| 1447 __ bind(&unordered); | 1447 __ bind(&unordered); |
| 1448 __ mov(ToRegister(result), Factory::false_value()); | 1448 __ mov(ToRegister(result), factory()->false_value()); |
| 1449 __ bind(&done); | 1449 __ bind(&done); |
| 1450 } | 1450 } |
| 1451 | 1451 |
| 1452 | 1452 |
| 1453 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1453 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 1454 LOperand* left = instr->InputAt(0); | 1454 LOperand* left = instr->InputAt(0); |
| 1455 LOperand* right = instr->InputAt(1); | 1455 LOperand* right = instr->InputAt(1); |
| 1456 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1456 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1457 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1457 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1458 | 1458 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1469 EmitBranch(true_block, false_block, cc); | 1469 EmitBranch(true_block, false_block, cc); |
| 1470 } | 1470 } |
| 1471 | 1471 |
| 1472 | 1472 |
| 1473 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1473 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
| 1474 Register left = ToRegister(instr->InputAt(0)); | 1474 Register left = ToRegister(instr->InputAt(0)); |
| 1475 Register right = ToRegister(instr->InputAt(1)); | 1475 Register right = ToRegister(instr->InputAt(1)); |
| 1476 Register result = ToRegister(instr->result()); | 1476 Register result = ToRegister(instr->result()); |
| 1477 | 1477 |
| 1478 __ cmp(left, Operand(right)); | 1478 __ cmp(left, Operand(right)); |
| 1479 __ mov(result, Factory::true_value()); | 1479 __ mov(result, factory()->true_value()); |
| 1480 NearLabel done; | 1480 NearLabel done; |
| 1481 __ j(equal, &done); | 1481 __ j(equal, &done); |
| 1482 __ mov(result, Factory::false_value()); | 1482 __ mov(result, factory()->false_value()); |
| 1483 __ bind(&done); | 1483 __ bind(&done); |
| 1484 } | 1484 } |
| 1485 | 1485 |
| 1486 | 1486 |
| 1487 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1487 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
| 1488 Register left = ToRegister(instr->InputAt(0)); | 1488 Register left = ToRegister(instr->InputAt(0)); |
| 1489 Register right = ToRegister(instr->InputAt(1)); | 1489 Register right = ToRegister(instr->InputAt(1)); |
| 1490 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1490 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1491 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1491 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1492 | 1492 |
| 1493 __ cmp(left, Operand(right)); | 1493 __ cmp(left, Operand(right)); |
| 1494 EmitBranch(true_block, false_block, equal); | 1494 EmitBranch(true_block, false_block, equal); |
| 1495 } | 1495 } |
| 1496 | 1496 |
| 1497 | 1497 |
| 1498 void LCodeGen::DoIsNull(LIsNull* instr) { | 1498 void LCodeGen::DoIsNull(LIsNull* instr) { |
| 1499 Register reg = ToRegister(instr->InputAt(0)); | 1499 Register reg = ToRegister(instr->InputAt(0)); |
| 1500 Register result = ToRegister(instr->result()); | 1500 Register result = ToRegister(instr->result()); |
| 1501 | 1501 |
| 1502 // TODO(fsc): If the expression is known to be a smi, then it's | 1502 // TODO(fsc): If the expression is known to be a smi, then it's |
| 1503 // definitely not null. Materialize false. | 1503 // definitely not null. Materialize false. |
| 1504 | 1504 |
| 1505 __ cmp(reg, Factory::null_value()); | 1505 __ cmp(reg, factory()->null_value()); |
| 1506 if (instr->is_strict()) { | 1506 if (instr->is_strict()) { |
| 1507 __ mov(result, Factory::true_value()); | 1507 __ mov(result, factory()->true_value()); |
| 1508 NearLabel done; | 1508 NearLabel done; |
| 1509 __ j(equal, &done); | 1509 __ j(equal, &done); |
| 1510 __ mov(result, Factory::false_value()); | 1510 __ mov(result, factory()->false_value()); |
| 1511 __ bind(&done); | 1511 __ bind(&done); |
| 1512 } else { | 1512 } else { |
| 1513 NearLabel true_value, false_value, done; | 1513 NearLabel true_value, false_value, done; |
| 1514 __ j(equal, &true_value); | 1514 __ j(equal, &true_value); |
| 1515 __ cmp(reg, Factory::undefined_value()); | 1515 __ cmp(reg, factory()->undefined_value()); |
| 1516 __ j(equal, &true_value); | 1516 __ j(equal, &true_value); |
| 1517 __ test(reg, Immediate(kSmiTagMask)); | 1517 __ test(reg, Immediate(kSmiTagMask)); |
| 1518 __ j(zero, &false_value); | 1518 __ j(zero, &false_value); |
| 1519 // Check for undetectable objects by looking in the bit field in | 1519 // Check for undetectable objects by looking in the bit field in |
| 1520 // the map. The object has already been smi checked. | 1520 // the map. The object has already been smi checked. |
| 1521 Register scratch = result; | 1521 Register scratch = result; |
| 1522 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1522 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1523 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1523 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| 1524 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1524 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
| 1525 __ j(not_zero, &true_value); | 1525 __ j(not_zero, &true_value); |
| 1526 __ bind(&false_value); | 1526 __ bind(&false_value); |
| 1527 __ mov(result, Factory::false_value()); | 1527 __ mov(result, factory()->false_value()); |
| 1528 __ jmp(&done); | 1528 __ jmp(&done); |
| 1529 __ bind(&true_value); | 1529 __ bind(&true_value); |
| 1530 __ mov(result, Factory::true_value()); | 1530 __ mov(result, factory()->true_value()); |
| 1531 __ bind(&done); | 1531 __ bind(&done); |
| 1532 } | 1532 } |
| 1533 } | 1533 } |
| 1534 | 1534 |
| 1535 | 1535 |
| 1536 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1536 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
| 1537 Register reg = ToRegister(instr->InputAt(0)); | 1537 Register reg = ToRegister(instr->InputAt(0)); |
| 1538 | 1538 |
| 1539 // TODO(fsc): If the expression is known to be a smi, then it's | 1539 // TODO(fsc): If the expression is known to be a smi, then it's |
| 1540 // definitely not null. Jump to the false block. | 1540 // definitely not null. Jump to the false block. |
| 1541 | 1541 |
| 1542 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1542 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1543 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1543 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1544 | 1544 |
| 1545 __ cmp(reg, Factory::null_value()); | 1545 __ cmp(reg, factory()->null_value()); |
| 1546 if (instr->is_strict()) { | 1546 if (instr->is_strict()) { |
| 1547 EmitBranch(true_block, false_block, equal); | 1547 EmitBranch(true_block, false_block, equal); |
| 1548 } else { | 1548 } else { |
| 1549 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1549 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1550 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1550 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1551 __ j(equal, true_label); | 1551 __ j(equal, true_label); |
| 1552 __ cmp(reg, Factory::undefined_value()); | 1552 __ cmp(reg, factory()->undefined_value()); |
| 1553 __ j(equal, true_label); | 1553 __ j(equal, true_label); |
| 1554 __ test(reg, Immediate(kSmiTagMask)); | 1554 __ test(reg, Immediate(kSmiTagMask)); |
| 1555 __ j(zero, false_label); | 1555 __ j(zero, false_label); |
| 1556 // Check for undetectable objects by looking in the bit field in | 1556 // Check for undetectable objects by looking in the bit field in |
| 1557 // the map. The object has already been smi checked. | 1557 // the map. The object has already been smi checked. |
| 1558 Register scratch = ToRegister(instr->TempAt(0)); | 1558 Register scratch = ToRegister(instr->TempAt(0)); |
| 1559 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1559 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1560 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1560 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| 1561 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1561 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
| 1562 EmitBranch(true_block, false_block, not_zero); | 1562 EmitBranch(true_block, false_block, not_zero); |
| 1563 } | 1563 } |
| 1564 } | 1564 } |
| 1565 | 1565 |
| 1566 | 1566 |
| 1567 Condition LCodeGen::EmitIsObject(Register input, | 1567 Condition LCodeGen::EmitIsObject(Register input, |
| 1568 Register temp1, | 1568 Register temp1, |
| 1569 Register temp2, | 1569 Register temp2, |
| 1570 Label* is_not_object, | 1570 Label* is_not_object, |
| 1571 Label* is_object) { | 1571 Label* is_object) { |
| 1572 ASSERT(!input.is(temp1)); | 1572 ASSERT(!input.is(temp1)); |
| 1573 ASSERT(!input.is(temp2)); | 1573 ASSERT(!input.is(temp2)); |
| 1574 ASSERT(!temp1.is(temp2)); | 1574 ASSERT(!temp1.is(temp2)); |
| 1575 | 1575 |
| 1576 __ test(input, Immediate(kSmiTagMask)); | 1576 __ test(input, Immediate(kSmiTagMask)); |
| 1577 __ j(equal, is_not_object); | 1577 __ j(equal, is_not_object); |
| 1578 | 1578 |
| 1579 __ cmp(input, Factory::null_value()); | 1579 __ cmp(input, isolate()->factory()->null_value()); |
| 1580 __ j(equal, is_object); | 1580 __ j(equal, is_object); |
| 1581 | 1581 |
| 1582 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); | 1582 __ mov(temp1, FieldOperand(input, HeapObject::kMapOffset)); |
| 1583 // Undetectable objects behave like undefined. | 1583 // Undetectable objects behave like undefined. |
| 1584 __ movzx_b(temp2, FieldOperand(temp1, Map::kBitFieldOffset)); | 1584 __ movzx_b(temp2, FieldOperand(temp1, Map::kBitFieldOffset)); |
| 1585 __ test(temp2, Immediate(1 << Map::kIsUndetectable)); | 1585 __ test(temp2, Immediate(1 << Map::kIsUndetectable)); |
| 1586 __ j(not_zero, is_not_object); | 1586 __ j(not_zero, is_not_object); |
| 1587 | 1587 |
| 1588 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); | 1588 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); |
| 1589 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); | 1589 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); |
| 1590 __ j(below, is_not_object); | 1590 __ j(below, is_not_object); |
| 1591 __ cmp(temp2, LAST_JS_OBJECT_TYPE); | 1591 __ cmp(temp2, LAST_JS_OBJECT_TYPE); |
| 1592 return below_equal; | 1592 return below_equal; |
| 1593 } | 1593 } |
| 1594 | 1594 |
| 1595 | 1595 |
| 1596 void LCodeGen::DoIsObject(LIsObject* instr) { | 1596 void LCodeGen::DoIsObject(LIsObject* instr) { |
| 1597 Register reg = ToRegister(instr->InputAt(0)); | 1597 Register reg = ToRegister(instr->InputAt(0)); |
| 1598 Register result = ToRegister(instr->result()); | 1598 Register result = ToRegister(instr->result()); |
| 1599 Register temp = ToRegister(instr->TempAt(0)); | 1599 Register temp = ToRegister(instr->TempAt(0)); |
| 1600 Label is_false, is_true, done; | 1600 Label is_false, is_true, done; |
| 1601 | 1601 |
| 1602 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); | 1602 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); |
| 1603 __ j(true_cond, &is_true); | 1603 __ j(true_cond, &is_true); |
| 1604 | 1604 |
| 1605 __ bind(&is_false); | 1605 __ bind(&is_false); |
| 1606 __ mov(result, Factory::false_value()); | 1606 __ mov(result, factory()->false_value()); |
| 1607 __ jmp(&done); | 1607 __ jmp(&done); |
| 1608 | 1608 |
| 1609 __ bind(&is_true); | 1609 __ bind(&is_true); |
| 1610 __ mov(result, Factory::true_value()); | 1610 __ mov(result, factory()->true_value()); |
| 1611 | 1611 |
| 1612 __ bind(&done); | 1612 __ bind(&done); |
| 1613 } | 1613 } |
| 1614 | 1614 |
| 1615 | 1615 |
| 1616 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1616 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 1617 Register reg = ToRegister(instr->InputAt(0)); | 1617 Register reg = ToRegister(instr->InputAt(0)); |
| 1618 Register temp = ToRegister(instr->TempAt(0)); | 1618 Register temp = ToRegister(instr->TempAt(0)); |
| 1619 Register temp2 = ToRegister(instr->TempAt(1)); | 1619 Register temp2 = ToRegister(instr->TempAt(1)); |
| 1620 | 1620 |
| 1621 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1621 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1622 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1622 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1623 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1623 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1624 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1624 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1625 | 1625 |
| 1626 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); | 1626 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); |
| 1627 | 1627 |
| 1628 EmitBranch(true_block, false_block, true_cond); | 1628 EmitBranch(true_block, false_block, true_cond); |
| 1629 } | 1629 } |
| 1630 | 1630 |
| 1631 | 1631 |
| 1632 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1632 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
| 1633 Operand input = ToOperand(instr->InputAt(0)); | 1633 Operand input = ToOperand(instr->InputAt(0)); |
| 1634 Register result = ToRegister(instr->result()); | 1634 Register result = ToRegister(instr->result()); |
| 1635 | 1635 |
| 1636 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1636 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1637 __ test(input, Immediate(kSmiTagMask)); | 1637 __ test(input, Immediate(kSmiTagMask)); |
| 1638 __ mov(result, Factory::true_value()); | 1638 __ mov(result, factory()->true_value()); |
| 1639 NearLabel done; | 1639 NearLabel done; |
| 1640 __ j(zero, &done); | 1640 __ j(zero, &done); |
| 1641 __ mov(result, Factory::false_value()); | 1641 __ mov(result, factory()->false_value()); |
| 1642 __ bind(&done); | 1642 __ bind(&done); |
| 1643 } | 1643 } |
| 1644 | 1644 |
| 1645 | 1645 |
| 1646 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1646 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 1647 Operand input = ToOperand(instr->InputAt(0)); | 1647 Operand input = ToOperand(instr->InputAt(0)); |
| 1648 | 1648 |
| 1649 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1649 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1650 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1650 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1651 | 1651 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1677 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1677 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
| 1678 Register input = ToRegister(instr->InputAt(0)); | 1678 Register input = ToRegister(instr->InputAt(0)); |
| 1679 Register result = ToRegister(instr->result()); | 1679 Register result = ToRegister(instr->result()); |
| 1680 | 1680 |
| 1681 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1681 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1682 __ test(input, Immediate(kSmiTagMask)); | 1682 __ test(input, Immediate(kSmiTagMask)); |
| 1683 NearLabel done, is_false; | 1683 NearLabel done, is_false; |
| 1684 __ j(zero, &is_false); | 1684 __ j(zero, &is_false); |
| 1685 __ CmpObjectType(input, TestType(instr->hydrogen()), result); | 1685 __ CmpObjectType(input, TestType(instr->hydrogen()), result); |
| 1686 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); | 1686 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); |
| 1687 __ mov(result, Factory::true_value()); | 1687 __ mov(result, factory()->true_value()); |
| 1688 __ jmp(&done); | 1688 __ jmp(&done); |
| 1689 __ bind(&is_false); | 1689 __ bind(&is_false); |
| 1690 __ mov(result, Factory::false_value()); | 1690 __ mov(result, factory()->false_value()); |
| 1691 __ bind(&done); | 1691 __ bind(&done); |
| 1692 } | 1692 } |
| 1693 | 1693 |
| 1694 | 1694 |
| 1695 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1695 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 1696 Register input = ToRegister(instr->InputAt(0)); | 1696 Register input = ToRegister(instr->InputAt(0)); |
| 1697 Register temp = ToRegister(instr->TempAt(0)); | 1697 Register temp = ToRegister(instr->TempAt(0)); |
| 1698 | 1698 |
| 1699 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1699 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1700 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1700 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1720 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); | 1720 __ mov(result, FieldOperand(input, String::kHashFieldOffset)); |
| 1721 __ IndexFromHash(result, result); | 1721 __ IndexFromHash(result, result); |
| 1722 } | 1722 } |
| 1723 | 1723 |
| 1724 | 1724 |
| 1725 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1725 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
| 1726 Register input = ToRegister(instr->InputAt(0)); | 1726 Register input = ToRegister(instr->InputAt(0)); |
| 1727 Register result = ToRegister(instr->result()); | 1727 Register result = ToRegister(instr->result()); |
| 1728 | 1728 |
| 1729 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1729 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1730 __ mov(result, Factory::true_value()); | 1730 __ mov(result, factory()->true_value()); |
| 1731 __ test(FieldOperand(input, String::kHashFieldOffset), | 1731 __ test(FieldOperand(input, String::kHashFieldOffset), |
| 1732 Immediate(String::kContainsCachedArrayIndexMask)); | 1732 Immediate(String::kContainsCachedArrayIndexMask)); |
| 1733 NearLabel done; | 1733 NearLabel done; |
| 1734 __ j(zero, &done); | 1734 __ j(zero, &done); |
| 1735 __ mov(result, Factory::false_value()); | 1735 __ mov(result, factory()->false_value()); |
| 1736 __ bind(&done); | 1736 __ bind(&done); |
| 1737 } | 1737 } |
| 1738 | 1738 |
| 1739 | 1739 |
| 1740 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1740 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 1741 LHasCachedArrayIndexAndBranch* instr) { | 1741 LHasCachedArrayIndexAndBranch* instr) { |
| 1742 Register input = ToRegister(instr->InputAt(0)); | 1742 Register input = ToRegister(instr->InputAt(0)); |
| 1743 | 1743 |
| 1744 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1744 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1745 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1745 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1814 Register temp = ToRegister(instr->TempAt(0)); | 1814 Register temp = ToRegister(instr->TempAt(0)); |
| 1815 Handle<String> class_name = instr->hydrogen()->class_name(); | 1815 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1816 NearLabel done; | 1816 NearLabel done; |
| 1817 Label is_true, is_false; | 1817 Label is_true, is_false; |
| 1818 | 1818 |
| 1819 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); | 1819 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); |
| 1820 | 1820 |
| 1821 __ j(not_equal, &is_false); | 1821 __ j(not_equal, &is_false); |
| 1822 | 1822 |
| 1823 __ bind(&is_true); | 1823 __ bind(&is_true); |
| 1824 __ mov(result, Factory::true_value()); | 1824 __ mov(result, factory()->true_value()); |
| 1825 __ jmp(&done); | 1825 __ jmp(&done); |
| 1826 | 1826 |
| 1827 __ bind(&is_false); | 1827 __ bind(&is_false); |
| 1828 __ mov(result, Factory::false_value()); | 1828 __ mov(result, factory()->false_value()); |
| 1829 __ bind(&done); | 1829 __ bind(&done); |
| 1830 } | 1830 } |
| 1831 | 1831 |
| 1832 | 1832 |
| 1833 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1833 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 1834 Register input = ToRegister(instr->InputAt(0)); | 1834 Register input = ToRegister(instr->InputAt(0)); |
| 1835 Register temp = ToRegister(instr->TempAt(0)); | 1835 Register temp = ToRegister(instr->TempAt(0)); |
| 1836 Register temp2 = ToRegister(instr->TempAt(1)); | 1836 Register temp2 = ToRegister(instr->TempAt(1)); |
| 1837 if (input.is(temp)) { | 1837 if (input.is(temp)) { |
| 1838 // Swap. | 1838 // Swap. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1866 | 1866 |
| 1867 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1867 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1868 // Object and function are in fixed registers defined by the stub. | 1868 // Object and function are in fixed registers defined by the stub. |
| 1869 ASSERT(ToRegister(instr->context()).is(esi)); | 1869 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1870 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1870 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| 1871 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1871 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1872 | 1872 |
| 1873 NearLabel true_value, done; | 1873 NearLabel true_value, done; |
| 1874 __ test(eax, Operand(eax)); | 1874 __ test(eax, Operand(eax)); |
| 1875 __ j(zero, &true_value); | 1875 __ j(zero, &true_value); |
| 1876 __ mov(ToRegister(instr->result()), Factory::false_value()); | 1876 __ mov(ToRegister(instr->result()), factory()->false_value()); |
| 1877 __ jmp(&done); | 1877 __ jmp(&done); |
| 1878 __ bind(&true_value); | 1878 __ bind(&true_value); |
| 1879 __ mov(ToRegister(instr->result()), Factory::true_value()); | 1879 __ mov(ToRegister(instr->result()), factory()->true_value()); |
| 1880 __ bind(&done); | 1880 __ bind(&done); |
| 1881 } | 1881 } |
| 1882 | 1882 |
| 1883 | 1883 |
| 1884 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { | 1884 void LCodeGen::DoInstanceOfAndBranch(LInstanceOfAndBranch* instr) { |
| 1885 ASSERT(ToRegister(instr->context()).is(esi)); | 1885 ASSERT(ToRegister(instr->context()).is(esi)); |
| 1886 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1886 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1887 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1887 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1888 | 1888 |
| 1889 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 1889 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1921 __ test(object, Immediate(kSmiTagMask)); | 1921 __ test(object, Immediate(kSmiTagMask)); |
| 1922 __ j(zero, &false_result, not_taken); | 1922 __ j(zero, &false_result, not_taken); |
| 1923 | 1923 |
| 1924 // This is the inlined call site instanceof cache. The two occurences of the | 1924 // This is the inlined call site instanceof cache. The two occurences of the |
| 1925 // hole value will be patched to the last map/result pair generated by the | 1925 // hole value will be patched to the last map/result pair generated by the |
| 1926 // instanceof stub. | 1926 // instanceof stub. |
| 1927 NearLabel cache_miss; | 1927 NearLabel cache_miss; |
| 1928 Register map = ToRegister(instr->TempAt(0)); | 1928 Register map = ToRegister(instr->TempAt(0)); |
| 1929 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); | 1929 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 1930 __ bind(deferred->map_check()); // Label for calculating code patching. | 1930 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 1931 __ cmp(map, Factory::the_hole_value()); // Patched to cached map. | 1931 __ cmp(map, factory()->the_hole_value()); // Patched to cached map. |
| 1932 __ j(not_equal, &cache_miss, not_taken); | 1932 __ j(not_equal, &cache_miss, not_taken); |
| 1933 __ mov(eax, Factory::the_hole_value()); // Patched to either true or false. | 1933 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. |
| 1934 __ jmp(&done); | 1934 __ jmp(&done); |
| 1935 | 1935 |
| 1936 // The inlined call site cache did not match. Check for null and string | 1936 // The inlined call site cache did not match. Check for null and string |
| 1937 // before calling the deferred code. | 1937 // before calling the deferred code. |
| 1938 __ bind(&cache_miss); | 1938 __ bind(&cache_miss); |
| 1939 // Null is not an instance of anything. | 1939 // Null is not an instance of anything. |
| 1940 __ cmp(object, Factory::null_value()); | 1940 __ cmp(object, factory()->null_value()); |
| 1941 __ j(equal, &false_result); | 1941 __ j(equal, &false_result); |
| 1942 | 1942 |
| 1943 // String values are not instances of anything. | 1943 // String values are not instances of anything. |
| 1944 Condition is_string = masm_->IsObjectStringType(object, temp, temp); | 1944 Condition is_string = masm_->IsObjectStringType(object, temp, temp); |
| 1945 __ j(is_string, &false_result); | 1945 __ j(is_string, &false_result); |
| 1946 | 1946 |
| 1947 // Go to the deferred code. | 1947 // Go to the deferred code. |
| 1948 __ jmp(deferred->entry()); | 1948 __ jmp(deferred->entry()); |
| 1949 | 1949 |
| 1950 __ bind(&false_result); | 1950 __ bind(&false_result); |
| 1951 __ mov(ToRegister(instr->result()), Factory::false_value()); | 1951 __ mov(ToRegister(instr->result()), factory()->false_value()); |
| 1952 | 1952 |
| 1953 // Here result has either true or false. Deferred code also produces true or | 1953 // Here result has either true or false. Deferred code also produces true or |
| 1954 // false object. | 1954 // false object. |
| 1955 __ bind(deferred->exit()); | 1955 __ bind(deferred->exit()); |
| 1956 __ bind(&done); | 1956 __ bind(&done); |
| 1957 } | 1957 } |
| 1958 | 1958 |
| 1959 | 1959 |
| 1960 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | 1960 void LCodeGen::DoDeferredLInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, |
| 1961 Label* map_check) { | 1961 Label* map_check) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2013 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2013 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| 2014 CallCode(ic, RelocInfo::CODE_TARGET, instr, false); | 2014 CallCode(ic, RelocInfo::CODE_TARGET, instr, false); |
| 2015 | 2015 |
| 2016 Condition condition = ComputeCompareCondition(op); | 2016 Condition condition = ComputeCompareCondition(op); |
| 2017 if (op == Token::GT || op == Token::LTE) { | 2017 if (op == Token::GT || op == Token::LTE) { |
| 2018 condition = ReverseCondition(condition); | 2018 condition = ReverseCondition(condition); |
| 2019 } | 2019 } |
| 2020 NearLabel true_value, done; | 2020 NearLabel true_value, done; |
| 2021 __ test(eax, Operand(eax)); | 2021 __ test(eax, Operand(eax)); |
| 2022 __ j(condition, &true_value); | 2022 __ j(condition, &true_value); |
| 2023 __ mov(ToRegister(instr->result()), Factory::false_value()); | 2023 __ mov(ToRegister(instr->result()), factory()->false_value()); |
| 2024 __ jmp(&done); | 2024 __ jmp(&done); |
| 2025 __ bind(&true_value); | 2025 __ bind(&true_value); |
| 2026 __ mov(ToRegister(instr->result()), Factory::true_value()); | 2026 __ mov(ToRegister(instr->result()), factory()->true_value()); |
| 2027 __ bind(&done); | 2027 __ bind(&done); |
| 2028 } | 2028 } |
| 2029 | 2029 |
| 2030 | 2030 |
| 2031 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { | 2031 void LCodeGen::DoCmpTAndBranch(LCmpTAndBranch* instr) { |
| 2032 Token::Value op = instr->op(); | 2032 Token::Value op = instr->op(); |
| 2033 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 2033 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 2034 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 2034 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 2035 | 2035 |
| 2036 Handle<Code> ic = CompareIC::GetUninitialized(op); | 2036 Handle<Code> ic = CompareIC::GetUninitialized(op); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2060 __ mov(esp, ebp); | 2060 __ mov(esp, ebp); |
| 2061 __ pop(ebp); | 2061 __ pop(ebp); |
| 2062 __ Ret((ParameterCount() + 1) * kPointerSize, ecx); | 2062 __ Ret((ParameterCount() + 1) * kPointerSize, ecx); |
| 2063 } | 2063 } |
| 2064 | 2064 |
| 2065 | 2065 |
| 2066 void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) { | 2066 void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) { |
| 2067 Register result = ToRegister(instr->result()); | 2067 Register result = ToRegister(instr->result()); |
| 2068 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); | 2068 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); |
| 2069 if (instr->hydrogen()->check_hole_value()) { | 2069 if (instr->hydrogen()->check_hole_value()) { |
| 2070 __ cmp(result, Factory::the_hole_value()); | 2070 __ cmp(result, factory()->the_hole_value()); |
| 2071 DeoptimizeIf(equal, instr->environment()); | 2071 DeoptimizeIf(equal, instr->environment()); |
| 2072 } | 2072 } |
| 2073 } | 2073 } |
| 2074 | 2074 |
| 2075 | 2075 |
| 2076 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { | 2076 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
| 2077 Register object = ToRegister(instr->temp1()); | 2077 Register object = ToRegister(instr->temp1()); |
| 2078 Register address = ToRegister(instr->temp2()); | 2078 Register address = ToRegister(instr->temp2()); |
| 2079 Register value = ToRegister(instr->InputAt(0)); | 2079 Register value = ToRegister(instr->InputAt(0)); |
| 2080 Handle<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell()); | 2080 Handle<JSGlobalPropertyCell> cell_handle(instr->hydrogen()->cell()); |
| 2081 | 2081 |
| 2082 // If the cell we are storing to contains the hole it could have | 2082 // If the cell we are storing to contains the hole it could have |
| 2083 // been deleted from the property dictionary. In that case, we need | 2083 // been deleted from the property dictionary. In that case, we need |
| 2084 // to update the property details in the property dictionary to mark | 2084 // to update the property details in the property dictionary to mark |
| 2085 // it as no longer deleted. We deoptimize in that case. | 2085 // it as no longer deleted. We deoptimize in that case. |
| 2086 if (instr->hydrogen()->check_hole_value()) { | 2086 if (instr->hydrogen()->check_hole_value()) { |
| 2087 __ cmp(Operand::Cell(cell_handle), Factory::the_hole_value()); | 2087 __ cmp(Operand::Cell(cell_handle), factory()->the_hole_value()); |
| 2088 DeoptimizeIf(equal, instr->environment()); | 2088 DeoptimizeIf(equal, instr->environment()); |
| 2089 } | 2089 } |
| 2090 | 2090 |
| 2091 // Store the value. | 2091 // Store the value. |
| 2092 __ mov(object, Immediate(cell_handle)); | 2092 __ mov(object, Immediate(cell_handle)); |
| 2093 __ lea(address, FieldOperand(object, JSGlobalPropertyCell::kValueOffset)); | 2093 __ lea(address, FieldOperand(object, JSGlobalPropertyCell::kValueOffset)); |
| 2094 __ mov(Operand(address, 0), value); | 2094 __ mov(Operand(address, 0), value); |
| 2095 | 2095 |
| 2096 | 2096 |
| 2097 // Cells are always in the remembered set. | 2097 // Cells are always in the remembered set. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2129 } | 2129 } |
| 2130 } | 2130 } |
| 2131 | 2131 |
| 2132 | 2132 |
| 2133 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 2133 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 2134 ASSERT(ToRegister(instr->context()).is(esi)); | 2134 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2135 ASSERT(ToRegister(instr->object()).is(eax)); | 2135 ASSERT(ToRegister(instr->object()).is(eax)); |
| 2136 ASSERT(ToRegister(instr->result()).is(eax)); | 2136 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2137 | 2137 |
| 2138 __ mov(ecx, instr->name()); | 2138 __ mov(ecx, instr->name()); |
| 2139 Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Initialize)); | 2139 Handle<Code> ic(isolate()->builtins()->builtin(Builtins::LoadIC_Initialize)); |
| 2140 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2140 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2141 } | 2141 } |
| 2142 | 2142 |
| 2143 | 2143 |
| 2144 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 2144 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 2145 Register function = ToRegister(instr->function()); | 2145 Register function = ToRegister(instr->function()); |
| 2146 Register temp = ToRegister(instr->TempAt(0)); | 2146 Register temp = ToRegister(instr->TempAt(0)); |
| 2147 Register result = ToRegister(instr->result()); | 2147 Register result = ToRegister(instr->result()); |
| 2148 | 2148 |
| 2149 // Check that the function really is a function. | 2149 // Check that the function really is a function. |
| 2150 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 2150 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
| 2151 DeoptimizeIf(not_equal, instr->environment()); | 2151 DeoptimizeIf(not_equal, instr->environment()); |
| 2152 | 2152 |
| 2153 // Check whether the function has an instance prototype. | 2153 // Check whether the function has an instance prototype. |
| 2154 NearLabel non_instance; | 2154 NearLabel non_instance; |
| 2155 __ test_b(FieldOperand(result, Map::kBitFieldOffset), | 2155 __ test_b(FieldOperand(result, Map::kBitFieldOffset), |
| 2156 1 << Map::kHasNonInstancePrototype); | 2156 1 << Map::kHasNonInstancePrototype); |
| 2157 __ j(not_zero, &non_instance); | 2157 __ j(not_zero, &non_instance); |
| 2158 | 2158 |
| 2159 // Get the prototype or initial map from the function. | 2159 // Get the prototype or initial map from the function. |
| 2160 __ mov(result, | 2160 __ mov(result, |
| 2161 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 2161 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 2162 | 2162 |
| 2163 // Check that the function has a prototype or an initial map. | 2163 // Check that the function has a prototype or an initial map. |
| 2164 __ cmp(Operand(result), Immediate(Factory::the_hole_value())); | 2164 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); |
| 2165 DeoptimizeIf(equal, instr->environment()); | 2165 DeoptimizeIf(equal, instr->environment()); |
| 2166 | 2166 |
| 2167 // If the function does not have an initial map, we're done. | 2167 // If the function does not have an initial map, we're done. |
| 2168 NearLabel done; | 2168 NearLabel done; |
| 2169 __ CmpObjectType(result, MAP_TYPE, temp); | 2169 __ CmpObjectType(result, MAP_TYPE, temp); |
| 2170 __ j(not_equal, &done); | 2170 __ j(not_equal, &done); |
| 2171 | 2171 |
| 2172 // Get the prototype from the initial map. | 2172 // Get the prototype from the initial map. |
| 2173 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); | 2173 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); |
| 2174 __ jmp(&done); | 2174 __ jmp(&done); |
| 2175 | 2175 |
| 2176 // Non-instance prototype: Fetch prototype from constructor field | 2176 // Non-instance prototype: Fetch prototype from constructor field |
| 2177 // in the function's map. | 2177 // in the function's map. |
| 2178 __ bind(&non_instance); | 2178 __ bind(&non_instance); |
| 2179 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); | 2179 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); |
| 2180 | 2180 |
| 2181 // All done. | 2181 // All done. |
| 2182 __ bind(&done); | 2182 __ bind(&done); |
| 2183 } | 2183 } |
| 2184 | 2184 |
| 2185 | 2185 |
| 2186 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 2186 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 2187 Register result = ToRegister(instr->result()); | 2187 Register result = ToRegister(instr->result()); |
| 2188 Register input = ToRegister(instr->InputAt(0)); | 2188 Register input = ToRegister(instr->InputAt(0)); |
| 2189 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); | 2189 __ mov(result, FieldOperand(input, JSObject::kElementsOffset)); |
| 2190 if (FLAG_debug_code) { | 2190 if (FLAG_debug_code) { |
| 2191 NearLabel done; | 2191 NearLabel done; |
| 2192 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2192 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
| 2193 Immediate(Factory::fixed_array_map())); | 2193 Immediate(factory()->fixed_array_map())); |
| 2194 __ j(equal, &done); | 2194 __ j(equal, &done); |
| 2195 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2195 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
| 2196 Immediate(Factory::external_pixel_array_map())); | 2196 Immediate(factory()->external_pixel_array_map())); |
| 2197 __ j(equal, &done); | 2197 __ j(equal, &done); |
| 2198 __ cmp(FieldOperand(result, HeapObject::kMapOffset), | 2198 __ cmp(FieldOperand(result, HeapObject::kMapOffset), |
| 2199 Immediate(Factory::fixed_cow_array_map())); | 2199 Immediate(factory()->fixed_cow_array_map())); |
| 2200 __ Check(equal, "Check for fast elements or pixel array failed."); | 2200 __ Check(equal, "Check for fast elements or pixel array failed."); |
| 2201 __ bind(&done); | 2201 __ bind(&done); |
| 2202 } | 2202 } |
| 2203 } | 2203 } |
| 2204 | 2204 |
| 2205 | 2205 |
| 2206 void LCodeGen::DoLoadExternalArrayPointer( | 2206 void LCodeGen::DoLoadExternalArrayPointer( |
| 2207 LLoadExternalArrayPointer* instr) { | 2207 LLoadExternalArrayPointer* instr) { |
| 2208 Register result = ToRegister(instr->result()); | 2208 Register result = ToRegister(instr->result()); |
| 2209 Register input = ToRegister(instr->InputAt(0)); | 2209 Register input = ToRegister(instr->InputAt(0)); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2233 Register result = ToRegister(instr->result()); | 2233 Register result = ToRegister(instr->result()); |
| 2234 ASSERT(result.is(elements)); | 2234 ASSERT(result.is(elements)); |
| 2235 | 2235 |
| 2236 // Load the result. | 2236 // Load the result. |
| 2237 __ mov(result, FieldOperand(elements, | 2237 __ mov(result, FieldOperand(elements, |
| 2238 key, | 2238 key, |
| 2239 times_pointer_size, | 2239 times_pointer_size, |
| 2240 FixedArray::kHeaderSize)); | 2240 FixedArray::kHeaderSize)); |
| 2241 | 2241 |
| 2242 // Check for the hole value. | 2242 // Check for the hole value. |
| 2243 __ cmp(result, Factory::the_hole_value()); | 2243 __ cmp(result, factory()->the_hole_value()); |
| 2244 DeoptimizeIf(equal, instr->environment()); | 2244 DeoptimizeIf(equal, instr->environment()); |
| 2245 } | 2245 } |
| 2246 | 2246 |
| 2247 | 2247 |
| 2248 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) { | 2248 void LCodeGen::DoLoadPixelArrayElement(LLoadPixelArrayElement* instr) { |
| 2249 Register external_pointer = ToRegister(instr->external_pointer()); | 2249 Register external_pointer = ToRegister(instr->external_pointer()); |
| 2250 Register key = ToRegister(instr->key()); | 2250 Register key = ToRegister(instr->key()); |
| 2251 Register result = ToRegister(instr->result()); | 2251 Register result = ToRegister(instr->result()); |
| 2252 ASSERT(result.is(external_pointer)); | 2252 ASSERT(result.is(external_pointer)); |
| 2253 | 2253 |
| 2254 // Load the result. | 2254 // Load the result. |
| 2255 __ movzx_b(result, Operand(external_pointer, key, times_1, 0)); | 2255 __ movzx_b(result, Operand(external_pointer, key, times_1, 0)); |
| 2256 } | 2256 } |
| 2257 | 2257 |
| 2258 | 2258 |
| 2259 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2259 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
| 2260 ASSERT(ToRegister(instr->context()).is(esi)); | 2260 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2261 ASSERT(ToRegister(instr->object()).is(edx)); | 2261 ASSERT(ToRegister(instr->object()).is(edx)); |
| 2262 ASSERT(ToRegister(instr->key()).is(eax)); | 2262 ASSERT(ToRegister(instr->key()).is(eax)); |
| 2263 | 2263 |
| 2264 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 2264 Handle<Code> ic(isolate()->builtins()->builtin( |
| 2265 Builtins::KeyedLoadIC_Initialize)); |
| 2265 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2266 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2266 } | 2267 } |
| 2267 | 2268 |
| 2268 | 2269 |
| 2269 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 2270 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
| 2270 Register result = ToRegister(instr->result()); | 2271 Register result = ToRegister(instr->result()); |
| 2271 | 2272 |
| 2272 // Check for arguments adapter frame. | 2273 // Check for arguments adapter frame. |
| 2273 NearLabel done, adapted; | 2274 NearLabel done, adapted; |
| 2274 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2275 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2319 Register length = ToRegister(instr->length()); | 2320 Register length = ToRegister(instr->length()); |
| 2320 Register elements = ToRegister(instr->elements()); | 2321 Register elements = ToRegister(instr->elements()); |
| 2321 Register scratch = ToRegister(instr->TempAt(0)); | 2322 Register scratch = ToRegister(instr->TempAt(0)); |
| 2322 ASSERT(receiver.is(eax)); // Used for parameter count. | 2323 ASSERT(receiver.is(eax)); // Used for parameter count. |
| 2323 ASSERT(function.is(edi)); // Required by InvokeFunction. | 2324 ASSERT(function.is(edi)); // Required by InvokeFunction. |
| 2324 ASSERT(ToRegister(instr->result()).is(eax)); | 2325 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2325 | 2326 |
| 2326 // If the receiver is null or undefined, we have to pass the global object | 2327 // If the receiver is null or undefined, we have to pass the global object |
| 2327 // as a receiver. | 2328 // as a receiver. |
| 2328 NearLabel global_object, receiver_ok; | 2329 NearLabel global_object, receiver_ok; |
| 2329 __ cmp(receiver, Factory::null_value()); | 2330 __ cmp(receiver, factory()->null_value()); |
| 2330 __ j(equal, &global_object); | 2331 __ j(equal, &global_object); |
| 2331 __ cmp(receiver, Factory::undefined_value()); | 2332 __ cmp(receiver, factory()->undefined_value()); |
| 2332 __ j(equal, &global_object); | 2333 __ j(equal, &global_object); |
| 2333 | 2334 |
| 2334 // The receiver should be a JS object. | 2335 // The receiver should be a JS object. |
| 2335 __ test(receiver, Immediate(kSmiTagMask)); | 2336 __ test(receiver, Immediate(kSmiTagMask)); |
| 2336 DeoptimizeIf(equal, instr->environment()); | 2337 DeoptimizeIf(equal, instr->environment()); |
| 2337 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); | 2338 __ CmpObjectType(receiver, FIRST_JS_OBJECT_TYPE, scratch); |
| 2338 DeoptimizeIf(below, instr->environment()); | 2339 DeoptimizeIf(below, instr->environment()); |
| 2339 __ jmp(&receiver_ok); | 2340 __ jmp(&receiver_ok); |
| 2340 | 2341 |
| 2341 __ bind(&global_object); | 2342 __ bind(&global_object); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2459 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2460 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 2460 ASSERT(ToRegister(instr->result()).is(eax)); | 2461 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2461 __ mov(edi, instr->function()); | 2462 __ mov(edi, instr->function()); |
| 2462 CallKnownFunction(instr->function(), instr->arity(), instr); | 2463 CallKnownFunction(instr->function(), instr->arity(), instr); |
| 2463 } | 2464 } |
| 2464 | 2465 |
| 2465 | 2466 |
| 2466 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2467 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2467 Register input_reg = ToRegister(instr->InputAt(0)); | 2468 Register input_reg = ToRegister(instr->InputAt(0)); |
| 2468 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 2469 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 2469 Factory::heap_number_map()); | 2470 factory()->heap_number_map()); |
| 2470 DeoptimizeIf(not_equal, instr->environment()); | 2471 DeoptimizeIf(not_equal, instr->environment()); |
| 2471 | 2472 |
| 2472 Label done; | 2473 Label done; |
| 2473 Register tmp = input_reg.is(eax) ? ecx : eax; | 2474 Register tmp = input_reg.is(eax) ? ecx : eax; |
| 2474 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; | 2475 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; |
| 2475 | 2476 |
| 2476 // Preserve the value of all registers. | 2477 // Preserve the value of all registers. |
| 2477 __ PushSafepointRegisters(); | 2478 __ PushSafepointRegisters(); |
| 2478 | 2479 |
| 2479 Label negative; | 2480 Label negative; |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2754 } | 2755 } |
| 2755 } | 2756 } |
| 2756 | 2757 |
| 2757 | 2758 |
| 2758 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 2759 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 2759 ASSERT(ToRegister(instr->context()).is(esi)); | 2760 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2760 ASSERT(ToRegister(instr->key()).is(ecx)); | 2761 ASSERT(ToRegister(instr->key()).is(ecx)); |
| 2761 ASSERT(ToRegister(instr->result()).is(eax)); | 2762 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2762 | 2763 |
| 2763 int arity = instr->arity(); | 2764 int arity = instr->arity(); |
| 2764 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); | 2765 Handle<Code> ic = isolate()->stub_cache()-> |
| 2766 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); |
| 2765 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2767 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2766 } | 2768 } |
| 2767 | 2769 |
| 2768 | 2770 |
| 2769 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 2771 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| 2770 ASSERT(ToRegister(instr->context()).is(esi)); | 2772 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2771 ASSERT(ToRegister(instr->result()).is(eax)); | 2773 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2772 | 2774 |
| 2773 int arity = instr->arity(); | 2775 int arity = instr->arity(); |
| 2774 Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); | 2776 Handle<Code> ic = isolate()->stub_cache()-> |
| 2777 ComputeCallInitialize(arity, NOT_IN_LOOP); |
| 2775 __ mov(ecx, instr->name()); | 2778 __ mov(ecx, instr->name()); |
| 2776 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2779 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2777 } | 2780 } |
| 2778 | 2781 |
| 2779 | 2782 |
| 2780 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 2783 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
| 2781 ASSERT(ToRegister(instr->context()).is(esi)); | 2784 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2782 ASSERT(ToRegister(instr->result()).is(eax)); | 2785 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2783 | 2786 |
| 2784 int arity = instr->arity(); | 2787 int arity = instr->arity(); |
| 2785 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); | 2788 CallFunctionStub stub(arity, NOT_IN_LOOP, RECEIVER_MIGHT_BE_VALUE); |
| 2786 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2789 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 2787 __ Drop(1); | 2790 __ Drop(1); |
| 2788 } | 2791 } |
| 2789 | 2792 |
| 2790 | 2793 |
| 2791 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 2794 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
| 2792 ASSERT(ToRegister(instr->context()).is(esi)); | 2795 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2793 ASSERT(ToRegister(instr->result()).is(eax)); | 2796 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2794 | 2797 |
| 2795 int arity = instr->arity(); | 2798 int arity = instr->arity(); |
| 2796 Handle<Code> ic = StubCache::ComputeCallInitialize(arity, NOT_IN_LOOP); | 2799 Handle<Code> ic = isolate()->stub_cache()-> |
| 2800 ComputeCallInitialize(arity, NOT_IN_LOOP); |
| 2797 __ mov(ecx, instr->name()); | 2801 __ mov(ecx, instr->name()); |
| 2798 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 2802 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); |
| 2799 } | 2803 } |
| 2800 | 2804 |
| 2801 | 2805 |
| 2802 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 2806 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 2803 ASSERT(ToRegister(instr->result()).is(eax)); | 2807 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2804 __ mov(edi, instr->target()); | 2808 __ mov(edi, instr->target()); |
| 2805 CallKnownFunction(instr->target(), instr->arity(), instr); | 2809 CallKnownFunction(instr->target(), instr->arity(), instr); |
| 2806 } | 2810 } |
| 2807 | 2811 |
| 2808 | 2812 |
| 2809 void LCodeGen::DoCallNew(LCallNew* instr) { | 2813 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 2810 ASSERT(ToRegister(instr->context()).is(esi)); | 2814 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2811 ASSERT(ToRegister(instr->constructor()).is(edi)); | 2815 ASSERT(ToRegister(instr->constructor()).is(edi)); |
| 2812 ASSERT(ToRegister(instr->result()).is(eax)); | 2816 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2813 | 2817 |
| 2814 Handle<Code> builtin(Builtins::builtin(Builtins::JSConstructCall)); | 2818 Handle<Code> builtin(isolate()->builtins()->builtin( |
| 2819 Builtins::JSConstructCall)); |
| 2815 __ Set(eax, Immediate(instr->arity())); | 2820 __ Set(eax, Immediate(instr->arity())); |
| 2816 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); | 2821 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
| 2817 } | 2822 } |
| 2818 | 2823 |
| 2819 | 2824 |
| 2820 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 2825 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 2821 CallRuntime(instr->function(), instr->arity(), instr, false); | 2826 CallRuntime(instr->function(), instr->arity(), instr, false); |
| 2822 } | 2827 } |
| 2823 | 2828 |
| 2824 | 2829 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2851 } | 2856 } |
| 2852 } | 2857 } |
| 2853 | 2858 |
| 2854 | 2859 |
| 2855 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 2860 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 2856 ASSERT(ToRegister(instr->context()).is(esi)); | 2861 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2857 ASSERT(ToRegister(instr->object()).is(edx)); | 2862 ASSERT(ToRegister(instr->object()).is(edx)); |
| 2858 ASSERT(ToRegister(instr->value()).is(eax)); | 2863 ASSERT(ToRegister(instr->value()).is(eax)); |
| 2859 | 2864 |
| 2860 __ mov(ecx, instr->name()); | 2865 __ mov(ecx, instr->name()); |
| 2861 Handle<Code> ic(Builtins::builtin( | 2866 Handle<Code> ic(isolate()->builtins()->builtin( |
| 2862 info_->is_strict() ? Builtins::StoreIC_Initialize_Strict | 2867 info_->is_strict() ? Builtins::StoreIC_Initialize_Strict |
| 2863 : Builtins::StoreIC_Initialize)); | 2868 : Builtins::StoreIC_Initialize)); |
| 2864 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2869 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2865 } | 2870 } |
| 2866 | 2871 |
| 2867 | 2872 |
| 2868 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { | 2873 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { |
| 2869 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 2874 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
| 2870 DeoptimizeIf(above_equal, instr->environment()); | 2875 DeoptimizeIf(above_equal, instr->environment()); |
| 2871 } | 2876 } |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2921 } | 2926 } |
| 2922 } | 2927 } |
| 2923 | 2928 |
| 2924 | 2929 |
| 2925 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 2930 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
| 2926 ASSERT(ToRegister(instr->context()).is(esi)); | 2931 ASSERT(ToRegister(instr->context()).is(esi)); |
| 2927 ASSERT(ToRegister(instr->object()).is(edx)); | 2932 ASSERT(ToRegister(instr->object()).is(edx)); |
| 2928 ASSERT(ToRegister(instr->key()).is(ecx)); | 2933 ASSERT(ToRegister(instr->key()).is(ecx)); |
| 2929 ASSERT(ToRegister(instr->value()).is(eax)); | 2934 ASSERT(ToRegister(instr->value()).is(eax)); |
| 2930 | 2935 |
| 2931 Handle<Code> ic(Builtins::builtin( | 2936 Handle<Code> ic(isolate()->builtins()->builtin( |
| 2932 info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict | 2937 info_->is_strict() ? Builtins::KeyedStoreIC_Initialize_Strict |
| 2933 : Builtins::KeyedStoreIC_Initialize)); | 2938 : Builtins::KeyedStoreIC_Initialize)); |
| 2934 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2939 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2935 } | 2940 } |
| 2936 | 2941 |
| 2937 | 2942 |
| 2938 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 2943 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 2939 class DeferredStringCharCodeAt: public LDeferredCode { | 2944 class DeferredStringCharCodeAt: public LDeferredCode { |
| 2940 public: | 2945 public: |
| 2941 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 2946 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2983 // Handle non-flat strings. | 2988 // Handle non-flat strings. |
| 2984 __ test(result, Immediate(kIsConsStringMask)); | 2989 __ test(result, Immediate(kIsConsStringMask)); |
| 2985 __ j(zero, deferred->entry()); | 2990 __ j(zero, deferred->entry()); |
| 2986 | 2991 |
| 2987 // ConsString. | 2992 // ConsString. |
| 2988 // Check whether the right hand side is the empty string (i.e. if | 2993 // Check whether the right hand side is the empty string (i.e. if |
| 2989 // this is really a flat string in a cons string). If that is not | 2994 // this is really a flat string in a cons string). If that is not |
| 2990 // the case we would rather go to the runtime system now to flatten | 2995 // the case we would rather go to the runtime system now to flatten |
| 2991 // the string. | 2996 // the string. |
| 2992 __ cmp(FieldOperand(string, ConsString::kSecondOffset), | 2997 __ cmp(FieldOperand(string, ConsString::kSecondOffset), |
| 2993 Immediate(Factory::empty_string())); | 2998 Immediate(factory()->empty_string())); |
| 2994 __ j(not_equal, deferred->entry()); | 2999 __ j(not_equal, deferred->entry()); |
| 2995 // Get the first of the two strings and load its instance type. | 3000 // Get the first of the two strings and load its instance type. |
| 2996 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); | 3001 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); |
| 2997 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); | 3002 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |
| 2998 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 3003 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 2999 // If the first cons component is also non-flat, then go to runtime. | 3004 // If the first cons component is also non-flat, then go to runtime. |
| 3000 STATIC_ASSERT(kSeqStringTag == 0); | 3005 STATIC_ASSERT(kSeqStringTag == 0); |
| 3001 __ test(result, Immediate(kStringRepresentationMask)); | 3006 __ test(result, Immediate(kStringRepresentationMask)); |
| 3002 __ j(not_zero, deferred->entry()); | 3007 __ j(not_zero, deferred->entry()); |
| 3003 | 3008 |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3088 DeferredStringCharFromCode* deferred = | 3093 DeferredStringCharFromCode* deferred = |
| 3089 new DeferredStringCharFromCode(this, instr); | 3094 new DeferredStringCharFromCode(this, instr); |
| 3090 | 3095 |
| 3091 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); | 3096 ASSERT(instr->hydrogen()->value()->representation().IsInteger32()); |
| 3092 Register char_code = ToRegister(instr->char_code()); | 3097 Register char_code = ToRegister(instr->char_code()); |
| 3093 Register result = ToRegister(instr->result()); | 3098 Register result = ToRegister(instr->result()); |
| 3094 ASSERT(!char_code.is(result)); | 3099 ASSERT(!char_code.is(result)); |
| 3095 | 3100 |
| 3096 __ cmp(char_code, String::kMaxAsciiCharCode); | 3101 __ cmp(char_code, String::kMaxAsciiCharCode); |
| 3097 __ j(above, deferred->entry()); | 3102 __ j(above, deferred->entry()); |
| 3098 __ Set(result, Immediate(Factory::single_character_string_cache())); | 3103 __ Set(result, Immediate(factory()->single_character_string_cache())); |
| 3099 __ mov(result, FieldOperand(result, | 3104 __ mov(result, FieldOperand(result, |
| 3100 char_code, times_pointer_size, | 3105 char_code, times_pointer_size, |
| 3101 FixedArray::kHeaderSize)); | 3106 FixedArray::kHeaderSize)); |
| 3102 __ cmp(result, Factory::undefined_value()); | 3107 __ cmp(result, factory()->undefined_value()); |
| 3103 __ j(equal, deferred->entry()); | 3108 __ j(equal, deferred->entry()); |
| 3104 __ bind(deferred->exit()); | 3109 __ bind(deferred->exit()); |
| 3105 } | 3110 } |
| 3106 | 3111 |
| 3107 | 3112 |
| 3108 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { | 3113 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { |
| 3109 Register char_code = ToRegister(instr->char_code()); | 3114 Register char_code = ToRegister(instr->char_code()); |
| 3110 Register result = ToRegister(instr->result()); | 3115 Register result = ToRegister(instr->result()); |
| 3111 | 3116 |
| 3112 // TODO(3095996): Get rid of this. For now, we need to make the | 3117 // TODO(3095996): Get rid of this. For now, we need to make the |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3270 XMMRegister result_reg, | 3275 XMMRegister result_reg, |
| 3271 LEnvironment* env) { | 3276 LEnvironment* env) { |
| 3272 NearLabel load_smi, heap_number, done; | 3277 NearLabel load_smi, heap_number, done; |
| 3273 | 3278 |
| 3274 // Smi check. | 3279 // Smi check. |
| 3275 __ test(input_reg, Immediate(kSmiTagMask)); | 3280 __ test(input_reg, Immediate(kSmiTagMask)); |
| 3276 __ j(zero, &load_smi, not_taken); | 3281 __ j(zero, &load_smi, not_taken); |
| 3277 | 3282 |
| 3278 // Heap number map check. | 3283 // Heap number map check. |
| 3279 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3284 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3280 Factory::heap_number_map()); | 3285 factory()->heap_number_map()); |
| 3281 __ j(equal, &heap_number); | 3286 __ j(equal, &heap_number); |
| 3282 | 3287 |
| 3283 __ cmp(input_reg, Factory::undefined_value()); | 3288 __ cmp(input_reg, factory()->undefined_value()); |
| 3284 DeoptimizeIf(not_equal, env); | 3289 DeoptimizeIf(not_equal, env); |
| 3285 | 3290 |
| 3286 // Convert undefined to NaN. | 3291 // Convert undefined to NaN. |
| 3287 ExternalReference nan = ExternalReference::address_of_nan(); | 3292 ExternalReference nan = ExternalReference::address_of_nan(); |
| 3288 __ movdbl(result_reg, Operand::StaticVariable(nan)); | 3293 __ movdbl(result_reg, Operand::StaticVariable(nan)); |
| 3289 __ jmp(&done); | 3294 __ jmp(&done); |
| 3290 | 3295 |
| 3291 // Heap number to XMM conversion. | 3296 // Heap number to XMM conversion. |
| 3292 __ bind(&heap_number); | 3297 __ bind(&heap_number); |
| 3293 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3298 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3311 LTaggedToI* instr_; | 3316 LTaggedToI* instr_; |
| 3312 }; | 3317 }; |
| 3313 | 3318 |
| 3314 | 3319 |
| 3315 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 3320 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 3316 NearLabel done, heap_number; | 3321 NearLabel done, heap_number; |
| 3317 Register input_reg = ToRegister(instr->InputAt(0)); | 3322 Register input_reg = ToRegister(instr->InputAt(0)); |
| 3318 | 3323 |
| 3319 // Heap number map check. | 3324 // Heap number map check. |
| 3320 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3325 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3321 Factory::heap_number_map()); | 3326 factory()->heap_number_map()); |
| 3322 | 3327 |
| 3323 if (instr->truncating()) { | 3328 if (instr->truncating()) { |
| 3324 __ j(equal, &heap_number); | 3329 __ j(equal, &heap_number); |
| 3325 // Check for undefined. Undefined is converted to zero for truncating | 3330 // Check for undefined. Undefined is converted to zero for truncating |
| 3326 // conversions. | 3331 // conversions. |
| 3327 __ cmp(input_reg, Factory::undefined_value()); | 3332 __ cmp(input_reg, factory()->undefined_value()); |
| 3328 DeoptimizeIf(not_equal, instr->environment()); | 3333 DeoptimizeIf(not_equal, instr->environment()); |
| 3329 __ mov(input_reg, 0); | 3334 __ mov(input_reg, 0); |
| 3330 __ jmp(&done); | 3335 __ jmp(&done); |
| 3331 | 3336 |
| 3332 __ bind(&heap_number); | 3337 __ bind(&heap_number); |
| 3333 if (CpuFeatures::IsSupported(SSE3)) { | 3338 if (isolate()->cpu_features()->IsSupported(SSE3)) { |
| 3334 CpuFeatures::Scope scope(SSE3); | 3339 CpuFeatures::Scope scope(SSE3); |
| 3335 NearLabel convert; | 3340 NearLabel convert; |
| 3336 // Use more powerful conversion when sse3 is available. | 3341 // Use more powerful conversion when sse3 is available. |
| 3337 // Load x87 register with heap number. | 3342 // Load x87 register with heap number. |
| 3338 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3343 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3339 // Get exponent alone and check for too-big exponent. | 3344 // Get exponent alone and check for too-big exponent. |
| 3340 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3345 __ mov(input_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 3341 __ and_(input_reg, HeapNumber::kExponentMask); | 3346 __ and_(input_reg, HeapNumber::kExponentMask); |
| 3342 const uint32_t kTooBigExponent = | 3347 const uint32_t kTooBigExponent = |
| 3343 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | 3348 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3433 ASSERT(result->IsRegister()); | 3438 ASSERT(result->IsRegister()); |
| 3434 | 3439 |
| 3435 XMMRegister input_reg = ToDoubleRegister(input); | 3440 XMMRegister input_reg = ToDoubleRegister(input); |
| 3436 Register result_reg = ToRegister(result); | 3441 Register result_reg = ToRegister(result); |
| 3437 | 3442 |
| 3438 if (instr->truncating()) { | 3443 if (instr->truncating()) { |
| 3439 // Performs a truncating conversion of a floating point number as used by | 3444 // Performs a truncating conversion of a floating point number as used by |
| 3440 // the JS bitwise operations. | 3445 // the JS bitwise operations. |
| 3441 __ cvttsd2si(result_reg, Operand(input_reg)); | 3446 __ cvttsd2si(result_reg, Operand(input_reg)); |
| 3442 __ cmp(result_reg, 0x80000000u); | 3447 __ cmp(result_reg, 0x80000000u); |
| 3443 if (CpuFeatures::IsSupported(SSE3)) { | 3448 if (isolate()->cpu_features()->IsSupported(SSE3)) { |
| 3444 // This will deoptimize if the exponent of the input in out of range. | 3449 // This will deoptimize if the exponent of the input in out of range. |
| 3445 CpuFeatures::Scope scope(SSE3); | 3450 CpuFeatures::Scope scope(SSE3); |
| 3446 NearLabel convert, done; | 3451 NearLabel convert, done; |
| 3447 __ j(not_equal, &done); | 3452 __ j(not_equal, &done); |
| 3448 __ sub(Operand(esp), Immediate(kDoubleSize)); | 3453 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 3449 __ movdbl(Operand(esp, 0), input_reg); | 3454 __ movdbl(Operand(esp, 0), input_reg); |
| 3450 // Get exponent alone and check for too-big exponent. | 3455 // Get exponent alone and check for too-big exponent. |
| 3451 __ mov(result_reg, Operand(esp, sizeof(int32_t))); | 3456 __ mov(result_reg, Operand(esp, sizeof(int32_t))); |
| 3452 __ and_(result_reg, HeapNumber::kExponentMask); | 3457 __ and_(result_reg, HeapNumber::kExponentMask); |
| 3453 const uint32_t kTooBigExponent = | 3458 const uint32_t kTooBigExponent = |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3600 LOperand* input = instr->InputAt(0); | 3605 LOperand* input = instr->InputAt(0); |
| 3601 ASSERT(input->IsRegister()); | 3606 ASSERT(input->IsRegister()); |
| 3602 Register reg = ToRegister(input); | 3607 Register reg = ToRegister(input); |
| 3603 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3608 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 3604 instr->hydrogen()->map()); | 3609 instr->hydrogen()->map()); |
| 3605 DeoptimizeIf(not_equal, instr->environment()); | 3610 DeoptimizeIf(not_equal, instr->environment()); |
| 3606 } | 3611 } |
| 3607 | 3612 |
| 3608 | 3613 |
| 3609 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { | 3614 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { |
| 3610 if (Heap::InNewSpace(*object)) { | 3615 if (isolate()->heap()->InNewSpace(*object)) { |
| 3611 Handle<JSGlobalPropertyCell> cell = | 3616 Handle<JSGlobalPropertyCell> cell = |
| 3612 Factory::NewJSGlobalPropertyCell(object); | 3617 isolate()->factory()->NewJSGlobalPropertyCell(object); |
| 3613 __ mov(result, Operand::Cell(cell)); | 3618 __ mov(result, Operand::Cell(cell)); |
| 3614 } else { | 3619 } else { |
| 3615 __ mov(result, object); | 3620 __ mov(result, object); |
| 3616 } | 3621 } |
| 3617 } | 3622 } |
| 3618 | 3623 |
| 3619 | 3624 |
| 3620 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 3625 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 3621 Register reg = ToRegister(instr->TempAt(0)); | 3626 Register reg = ToRegister(instr->TempAt(0)); |
| 3622 | 3627 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3695 // Registers will be used as follows: | 3700 // Registers will be used as follows: |
| 3696 // edi = JS function. | 3701 // edi = JS function. |
| 3697 // ecx = literals array. | 3702 // ecx = literals array. |
| 3698 // ebx = regexp literal. | 3703 // ebx = regexp literal. |
| 3699 // eax = regexp literal clone. | 3704 // eax = regexp literal clone. |
| 3700 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 3705 __ mov(edi, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3701 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); | 3706 __ mov(ecx, FieldOperand(edi, JSFunction::kLiteralsOffset)); |
| 3702 int literal_offset = FixedArray::kHeaderSize + | 3707 int literal_offset = FixedArray::kHeaderSize + |
| 3703 instr->hydrogen()->literal_index() * kPointerSize; | 3708 instr->hydrogen()->literal_index() * kPointerSize; |
| 3704 __ mov(ebx, FieldOperand(ecx, literal_offset)); | 3709 __ mov(ebx, FieldOperand(ecx, literal_offset)); |
| 3705 __ cmp(ebx, Factory::undefined_value()); | 3710 __ cmp(ebx, factory()->undefined_value()); |
| 3706 __ j(not_equal, &materialized); | 3711 __ j(not_equal, &materialized); |
| 3707 | 3712 |
| 3708 // Create regexp literal using runtime function | 3713 // Create regexp literal using runtime function |
| 3709 // Result will be in eax. | 3714 // Result will be in eax. |
| 3710 __ push(ecx); | 3715 __ push(ecx); |
| 3711 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 3716 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 3712 __ push(Immediate(instr->hydrogen()->pattern())); | 3717 __ push(Immediate(instr->hydrogen()->pattern())); |
| 3713 __ push(Immediate(instr->hydrogen()->flags())); | 3718 __ push(Immediate(instr->hydrogen()->flags())); |
| 3714 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, false); | 3719 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr, false); |
| 3715 __ mov(ebx, eax); | 3720 __ mov(ebx, eax); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3749 bool pretenure = instr->hydrogen()->pretenure(); | 3754 bool pretenure = instr->hydrogen()->pretenure(); |
| 3750 if (!pretenure && shared_info->num_literals() == 0) { | 3755 if (!pretenure && shared_info->num_literals() == 0) { |
| 3751 FastNewClosureStub stub( | 3756 FastNewClosureStub stub( |
| 3752 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); | 3757 shared_info->strict_mode() ? kStrictMode : kNonStrictMode); |
| 3753 __ push(Immediate(shared_info)); | 3758 __ push(Immediate(shared_info)); |
| 3754 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); | 3759 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr, false); |
| 3755 } else { | 3760 } else { |
| 3756 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); | 3761 __ push(Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 3757 __ push(Immediate(shared_info)); | 3762 __ push(Immediate(shared_info)); |
| 3758 __ push(Immediate(pretenure | 3763 __ push(Immediate(pretenure |
| 3759 ? Factory::true_value() | 3764 ? factory()->true_value() |
| 3760 : Factory::false_value())); | 3765 : factory()->false_value())); |
| 3761 CallRuntime(Runtime::kNewClosure, 3, instr, false); | 3766 CallRuntime(Runtime::kNewClosure, 3, instr, false); |
| 3762 } | 3767 } |
| 3763 } | 3768 } |
| 3764 | 3769 |
| 3765 | 3770 |
| 3766 void LCodeGen::DoTypeof(LTypeof* instr) { | 3771 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 3767 LOperand* input = instr->InputAt(0); | 3772 LOperand* input = instr->InputAt(0); |
| 3768 if (input->IsConstantOperand()) { | 3773 if (input->IsConstantOperand()) { |
| 3769 __ push(ToImmediate(input)); | 3774 __ push(ToImmediate(input)); |
| 3770 } else { | 3775 } else { |
| 3771 __ push(ToOperand(input)); | 3776 __ push(ToOperand(input)); |
| 3772 } | 3777 } |
| 3773 CallRuntime(Runtime::kTypeof, 1, instr, false); | 3778 CallRuntime(Runtime::kTypeof, 1, instr, false); |
| 3774 } | 3779 } |
| 3775 | 3780 |
| 3776 | 3781 |
| 3777 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 3782 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
| 3778 Register input = ToRegister(instr->InputAt(0)); | 3783 Register input = ToRegister(instr->InputAt(0)); |
| 3779 Register result = ToRegister(instr->result()); | 3784 Register result = ToRegister(instr->result()); |
| 3780 Label true_label; | 3785 Label true_label; |
| 3781 Label false_label; | 3786 Label false_label; |
| 3782 NearLabel done; | 3787 NearLabel done; |
| 3783 | 3788 |
| 3784 Condition final_branch_condition = EmitTypeofIs(&true_label, | 3789 Condition final_branch_condition = EmitTypeofIs(&true_label, |
| 3785 &false_label, | 3790 &false_label, |
| 3786 input, | 3791 input, |
| 3787 instr->type_literal()); | 3792 instr->type_literal()); |
| 3788 __ j(final_branch_condition, &true_label); | 3793 __ j(final_branch_condition, &true_label); |
| 3789 __ bind(&false_label); | 3794 __ bind(&false_label); |
| 3790 __ mov(result, Factory::false_value()); | 3795 __ mov(result, factory()->false_value()); |
| 3791 __ jmp(&done); | 3796 __ jmp(&done); |
| 3792 | 3797 |
| 3793 __ bind(&true_label); | 3798 __ bind(&true_label); |
| 3794 __ mov(result, Factory::true_value()); | 3799 __ mov(result, factory()->true_value()); |
| 3795 | 3800 |
| 3796 __ bind(&done); | 3801 __ bind(&done); |
| 3797 } | 3802 } |
| 3798 | 3803 |
| 3799 | 3804 |
| 3800 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 3805 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 3801 Register input = ToRegister(instr->InputAt(0)); | 3806 Register input = ToRegister(instr->InputAt(0)); |
| 3802 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 3807 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 3803 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 3808 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 3804 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 3809 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 3805 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 3810 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 3806 | 3811 |
| 3807 Condition final_branch_condition = EmitTypeofIs(true_label, | 3812 Condition final_branch_condition = EmitTypeofIs(true_label, |
| 3808 false_label, | 3813 false_label, |
| 3809 input, | 3814 input, |
| 3810 instr->type_literal()); | 3815 instr->type_literal()); |
| 3811 | 3816 |
| 3812 EmitBranch(true_block, false_block, final_branch_condition); | 3817 EmitBranch(true_block, false_block, final_branch_condition); |
| 3813 } | 3818 } |
| 3814 | 3819 |
| 3815 | 3820 |
| 3816 Condition LCodeGen::EmitTypeofIs(Label* true_label, | 3821 Condition LCodeGen::EmitTypeofIs(Label* true_label, |
| 3817 Label* false_label, | 3822 Label* false_label, |
| 3818 Register input, | 3823 Register input, |
| 3819 Handle<String> type_name) { | 3824 Handle<String> type_name) { |
| 3820 Condition final_branch_condition = no_condition; | 3825 Condition final_branch_condition = no_condition; |
| 3821 if (type_name->Equals(Heap::number_symbol())) { | 3826 if (type_name->Equals(heap()->number_symbol())) { |
| 3822 __ JumpIfSmi(input, true_label); | 3827 __ JumpIfSmi(input, true_label); |
| 3823 __ cmp(FieldOperand(input, HeapObject::kMapOffset), | 3828 __ cmp(FieldOperand(input, HeapObject::kMapOffset), |
| 3824 Factory::heap_number_map()); | 3829 factory()->heap_number_map()); |
| 3825 final_branch_condition = equal; | 3830 final_branch_condition = equal; |
| 3826 | 3831 |
| 3827 } else if (type_name->Equals(Heap::string_symbol())) { | 3832 } else if (type_name->Equals(heap()->string_symbol())) { |
| 3828 __ JumpIfSmi(input, false_label); | 3833 __ JumpIfSmi(input, false_label); |
| 3829 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); | 3834 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); |
| 3830 __ j(above_equal, false_label); | 3835 __ j(above_equal, false_label); |
| 3831 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 3836 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 3832 1 << Map::kIsUndetectable); | 3837 1 << Map::kIsUndetectable); |
| 3833 final_branch_condition = zero; | 3838 final_branch_condition = zero; |
| 3834 | 3839 |
| 3835 } else if (type_name->Equals(Heap::boolean_symbol())) { | 3840 } else if (type_name->Equals(heap()->boolean_symbol())) { |
| 3836 __ cmp(input, Factory::true_value()); | 3841 __ cmp(input, factory()->true_value()); |
| 3837 __ j(equal, true_label); | 3842 __ j(equal, true_label); |
| 3838 __ cmp(input, Factory::false_value()); | 3843 __ cmp(input, factory()->false_value()); |
| 3839 final_branch_condition = equal; | 3844 final_branch_condition = equal; |
| 3840 | 3845 |
| 3841 } else if (type_name->Equals(Heap::undefined_symbol())) { | 3846 } else if (type_name->Equals(heap()->undefined_symbol())) { |
| 3842 __ cmp(input, Factory::undefined_value()); | 3847 __ cmp(input, factory()->undefined_value()); |
| 3843 __ j(equal, true_label); | 3848 __ j(equal, true_label); |
| 3844 __ JumpIfSmi(input, false_label); | 3849 __ JumpIfSmi(input, false_label); |
| 3845 // Check for undetectable objects => true. | 3850 // Check for undetectable objects => true. |
| 3846 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); | 3851 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); |
| 3847 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 3852 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 3848 1 << Map::kIsUndetectable); | 3853 1 << Map::kIsUndetectable); |
| 3849 final_branch_condition = not_zero; | 3854 final_branch_condition = not_zero; |
| 3850 | 3855 |
| 3851 } else if (type_name->Equals(Heap::function_symbol())) { | 3856 } else if (type_name->Equals(heap()->function_symbol())) { |
| 3852 __ JumpIfSmi(input, false_label); | 3857 __ JumpIfSmi(input, false_label); |
| 3853 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); | 3858 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); |
| 3854 __ j(equal, true_label); | 3859 __ j(equal, true_label); |
| 3855 // Regular expressions => 'function' (they are callable). | 3860 // Regular expressions => 'function' (they are callable). |
| 3856 __ CmpInstanceType(input, JS_REGEXP_TYPE); | 3861 __ CmpInstanceType(input, JS_REGEXP_TYPE); |
| 3857 final_branch_condition = equal; | 3862 final_branch_condition = equal; |
| 3858 | 3863 |
| 3859 } else if (type_name->Equals(Heap::object_symbol())) { | 3864 } else if (type_name->Equals(heap()->object_symbol())) { |
| 3860 __ JumpIfSmi(input, false_label); | 3865 __ JumpIfSmi(input, false_label); |
| 3861 __ cmp(input, Factory::null_value()); | 3866 __ cmp(input, factory()->null_value()); |
| 3862 __ j(equal, true_label); | 3867 __ j(equal, true_label); |
| 3863 // Regular expressions => 'function', not 'object'. | 3868 // Regular expressions => 'function', not 'object'. |
| 3864 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input); | 3869 __ CmpObjectType(input, FIRST_JS_OBJECT_TYPE, input); |
| 3865 __ j(below, false_label); | 3870 __ j(below, false_label); |
| 3866 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE); | 3871 __ CmpInstanceType(input, FIRST_FUNCTION_CLASS_TYPE); |
| 3867 __ j(above_equal, false_label); | 3872 __ j(above_equal, false_label); |
| 3868 // Check for undetectable objects => false. | 3873 // Check for undetectable objects => false. |
| 3869 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 3874 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 3870 1 << Map::kIsUndetectable); | 3875 1 << Map::kIsUndetectable); |
| 3871 final_branch_condition = zero; | 3876 final_branch_condition = zero; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 3882 | 3887 |
| 3883 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { | 3888 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { |
| 3884 Register result = ToRegister(instr->result()); | 3889 Register result = ToRegister(instr->result()); |
| 3885 NearLabel true_label; | 3890 NearLabel true_label; |
| 3886 NearLabel false_label; | 3891 NearLabel false_label; |
| 3887 NearLabel done; | 3892 NearLabel done; |
| 3888 | 3893 |
| 3889 EmitIsConstructCall(result); | 3894 EmitIsConstructCall(result); |
| 3890 __ j(equal, &true_label); | 3895 __ j(equal, &true_label); |
| 3891 | 3896 |
| 3892 __ mov(result, Factory::false_value()); | 3897 __ mov(result, factory()->false_value()); |
| 3893 __ jmp(&done); | 3898 __ jmp(&done); |
| 3894 | 3899 |
| 3895 __ bind(&true_label); | 3900 __ bind(&true_label); |
| 3896 __ mov(result, Factory::true_value()); | 3901 __ mov(result, factory()->true_value()); |
| 3897 | 3902 |
| 3898 __ bind(&done); | 3903 __ bind(&done); |
| 3899 } | 3904 } |
| 3900 | 3905 |
| 3901 | 3906 |
| 3902 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { | 3907 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 3903 Register temp = ToRegister(instr->TempAt(0)); | 3908 Register temp = ToRegister(instr->TempAt(0)); |
| 3904 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 3909 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 3905 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 3910 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 3906 | 3911 |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3993 ASSERT(osr_pc_offset_ == -1); | 3998 ASSERT(osr_pc_offset_ == -1); |
| 3994 osr_pc_offset_ = masm()->pc_offset(); | 3999 osr_pc_offset_ = masm()->pc_offset(); |
| 3995 } | 4000 } |
| 3996 | 4001 |
| 3997 | 4002 |
| 3998 #undef __ | 4003 #undef __ |
| 3999 | 4004 |
| 4000 } } // namespace v8::internal | 4005 } } // namespace v8::internal |
| 4001 | 4006 |
| 4002 #endif // V8_TARGET_ARCH_IA32 | 4007 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |