| 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 30 matching lines...) Expand all Loading... |
| 41 // the invoke instruction sequence generated by the macro assembler. | 41 // the invoke instruction sequence generated by the macro assembler. |
| 42 class SafepointGenerator : public PostCallGenerator { | 42 class SafepointGenerator : public PostCallGenerator { |
| 43 public: | 43 public: |
| 44 SafepointGenerator(LCodeGen* codegen, | 44 SafepointGenerator(LCodeGen* codegen, |
| 45 LPointerMap* pointers, | 45 LPointerMap* pointers, |
| 46 int deoptimization_index, | 46 int deoptimization_index, |
| 47 bool ensure_reloc_space = false) | 47 bool ensure_reloc_space = false) |
| 48 : codegen_(codegen), | 48 : codegen_(codegen), |
| 49 pointers_(pointers), | 49 pointers_(pointers), |
| 50 deoptimization_index_(deoptimization_index), | 50 deoptimization_index_(deoptimization_index), |
| 51 ensure_reloc_space_(ensure_reloc_space) { } | 51 ensure_reloc_space_(ensure_reloc_space), |
| 52 previous_safepoint_position_(-kMinSafepointSize) { } |
| 52 virtual ~SafepointGenerator() { } | 53 virtual ~SafepointGenerator() { } |
| 53 | 54 |
| 54 virtual void Generate() { | 55 virtual void Generate() { |
| 56 // Ensure that we have enough space after the previous safepoint position |
| 57 // for the generated code there. |
| 58 int position = codegen_->masm()->pc_offset(); |
| 59 ASSERT(position > previous_safepoint_position_); |
| 60 if (position < previous_safepoint_position_ + kMinSafepointSize) { |
| 61 int padding_size = |
| 62 previous_safepoint_position_ + kMinSafepointSize - position; |
| 63 STATIC_ASSERT(kMinSafepointSize <= 9); // One multibyte nop is enough. |
| 64 codegen_->masm()->nop(padding_size); |
| 65 position += padding_size; |
| 66 } |
| 55 // Ensure that we have enough space in the reloc info to patch | 67 // Ensure that we have enough space in the reloc info to patch |
| 56 // this with calls when doing deoptimization. | 68 // this with calls when doing deoptimization. |
| 57 if (ensure_reloc_space_) { | 69 if (ensure_reloc_space_) { |
| 58 codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true); | 70 codegen_->masm()->RecordComment(RelocInfo::kFillerCommentString, true); |
| 59 } | 71 } |
| 60 codegen_->RecordSafepoint(pointers_, deoptimization_index_); | 72 codegen_->RecordSafepoint(pointers_, deoptimization_index_); |
| 73 previous_safepoint_position_ = position; |
| 61 } | 74 } |
| 62 | 75 |
| 63 private: | 76 private: |
| 77 static const int kMinSafepointSize = |
| 78 MacroAssembler::kShortCallInstructionLength; |
| 64 LCodeGen* codegen_; | 79 LCodeGen* codegen_; |
| 65 LPointerMap* pointers_; | 80 LPointerMap* pointers_; |
| 66 int deoptimization_index_; | 81 int deoptimization_index_; |
| 67 bool ensure_reloc_space_; | 82 bool ensure_reloc_space_; |
| 83 int previous_safepoint_position_; |
| 68 }; | 84 }; |
| 69 | 85 |
| 70 | 86 |
| 71 #define __ masm()-> | 87 #define __ masm()-> |
| 72 | 88 |
| 73 bool LCodeGen::GenerateCode() { | 89 bool LCodeGen::GenerateCode() { |
| 74 HPhase phase("Code generation", chunk()); | 90 HPhase phase("Code generation", chunk()); |
| 75 ASSERT(is_unused()); | 91 ASSERT(is_unused()); |
| 76 status_ = GENERATING; | 92 status_ = GENERATING; |
| 77 return GeneratePrologue() && | 93 return GeneratePrologue() && |
| 78 GenerateBody() && | 94 GenerateBody() && |
| 79 GenerateDeferredCode() && | 95 GenerateDeferredCode() && |
| 80 GenerateJumpTable() && | 96 GenerateJumpTable() && |
| 81 GenerateSafepointTable(); | 97 GenerateSafepointTable(); |
| 82 } | 98 } |
| 83 | 99 |
| 84 | 100 |
| 85 void LCodeGen::FinishCode(Handle<Code> code) { | 101 void LCodeGen::FinishCode(Handle<Code> code) { |
| 86 ASSERT(is_done()); | 102 ASSERT(is_done()); |
| 87 code->set_stack_slots(StackSlotCount()); | 103 code->set_stack_slots(StackSlotCount()); |
| 88 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); | 104 code->set_safepoint_table_offset(safepoints_.GetCodeOffset()); |
| 89 PopulateDeoptimizationData(code); | 105 PopulateDeoptimizationData(code); |
| 90 } | 106 } |
| 91 | 107 |
| 92 | 108 |
| 93 void LCodeGen::Abort(const char* format, ...) { | 109 void LCodeGen::Abort(const char* format, ...) { |
| 94 if (FLAG_trace_bailout) { | 110 if (FLAG_trace_bailout) { |
| 95 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); | 111 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString()); |
| 96 PrintF("Aborting LCodeGen in @\"%s\": ", *debug_name); | 112 PrintF("Aborting LCodeGen in @\"%s\": ", *name); |
| 97 va_list arguments; | 113 va_list arguments; |
| 98 va_start(arguments, format); | 114 va_start(arguments, format); |
| 99 OS::VPrint(format, arguments); | 115 OS::VPrint(format, arguments); |
| 100 va_end(arguments); | 116 va_end(arguments); |
| 101 PrintF("\n"); | 117 PrintF("\n"); |
| 102 } | 118 } |
| 103 status_ = ABORTED; | 119 status_ = ABORTED; |
| 104 } | 120 } |
| 105 | 121 |
| 106 | 122 |
| (...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 return; | 1441 return; |
| 1426 } | 1442 } |
| 1427 | 1443 |
| 1428 __ CompareRoot(reg, Heap::kNullValueRootIndex); | 1444 __ CompareRoot(reg, Heap::kNullValueRootIndex); |
| 1429 if (instr->is_strict()) { | 1445 if (instr->is_strict()) { |
| 1430 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); | 1446 __ movl(result, Immediate(Heap::kTrueValueRootIndex)); |
| 1431 NearLabel load; | 1447 NearLabel load; |
| 1432 __ j(equal, &load); | 1448 __ j(equal, &load); |
| 1433 __ movl(result, Immediate(Heap::kFalseValueRootIndex)); | 1449 __ movl(result, Immediate(Heap::kFalseValueRootIndex)); |
| 1434 __ bind(&load); | 1450 __ bind(&load); |
| 1435 __ movq(result, Operand(kRootRegister, result, times_pointer_size, 0)); | 1451 __ LoadRootIndexed(result, result, 0); |
| 1436 } else { | 1452 } else { |
| 1437 NearLabel true_value, false_value, done; | 1453 NearLabel true_value, false_value, done; |
| 1438 __ j(equal, &true_value); | 1454 __ j(equal, &true_value); |
| 1439 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); | 1455 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); |
| 1440 __ j(equal, &true_value); | 1456 __ j(equal, &true_value); |
| 1441 __ JumpIfSmi(reg, &false_value); | 1457 __ JumpIfSmi(reg, &false_value); |
| 1442 // Check for undetectable objects by looking in the bit field in | 1458 // Check for undetectable objects by looking in the bit field in |
| 1443 // the map. The object has already been smi checked. | 1459 // the map. The object has already been smi checked. |
| 1444 Register scratch = result; | 1460 Register scratch = result; |
| 1445 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1461 __ movq(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1556 Register result = ToRegister(instr->result()); | 1572 Register result = ToRegister(instr->result()); |
| 1557 if (input_operand->IsRegister()) { | 1573 if (input_operand->IsRegister()) { |
| 1558 Register input = ToRegister(input_operand); | 1574 Register input = ToRegister(input_operand); |
| 1559 __ CheckSmiToIndicator(result, input); | 1575 __ CheckSmiToIndicator(result, input); |
| 1560 } else { | 1576 } else { |
| 1561 Operand input = ToOperand(instr->InputAt(0)); | 1577 Operand input = ToOperand(instr->InputAt(0)); |
| 1562 __ CheckSmiToIndicator(result, input); | 1578 __ CheckSmiToIndicator(result, input); |
| 1563 } | 1579 } |
| 1564 // result is zero if input is a smi, and one otherwise. | 1580 // result is zero if input is a smi, and one otherwise. |
| 1565 ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1); | 1581 ASSERT(Heap::kFalseValueRootIndex == Heap::kTrueValueRootIndex + 1); |
| 1566 __ movq(result, Operand(kRootRegister, result, times_pointer_size, | 1582 __ LoadRootIndexed(result, result, Heap::kTrueValueRootIndex); |
| 1567 Heap::kTrueValueRootIndex * kPointerSize)); | |
| 1568 } | 1583 } |
| 1569 | 1584 |
| 1570 | 1585 |
| 1571 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1586 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 1572 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1587 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1573 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1588 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1574 | 1589 |
| 1575 Condition is_smi; | 1590 Condition is_smi; |
| 1576 if (instr->InputAt(0)->IsRegister()) { | 1591 if (instr->InputAt(0)->IsRegister()) { |
| 1577 Register input = ToRegister(instr->InputAt(0)); | 1592 Register input = ToRegister(instr->InputAt(0)); |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1971 __ movq(result, ContextOperand(context, instr->slot_index())); | 1986 __ movq(result, ContextOperand(context, instr->slot_index())); |
| 1972 } | 1987 } |
| 1973 | 1988 |
| 1974 | 1989 |
| 1975 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 1990 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
| 1976 Register context = ToRegister(instr->context()); | 1991 Register context = ToRegister(instr->context()); |
| 1977 Register value = ToRegister(instr->value()); | 1992 Register value = ToRegister(instr->value()); |
| 1978 __ movq(ContextOperand(context, instr->slot_index()), value); | 1993 __ movq(ContextOperand(context, instr->slot_index()), value); |
| 1979 if (instr->needs_write_barrier()) { | 1994 if (instr->needs_write_barrier()) { |
| 1980 int offset = Context::SlotOffset(instr->slot_index()); | 1995 int offset = Context::SlotOffset(instr->slot_index()); |
| 1981 __ RecordWrite(context, offset, value, kScratchRegister); | 1996 Register scratch = ToRegister(instr->TempAt(0)); |
| 1997 __ RecordWrite(context, offset, value, scratch); |
| 1982 } | 1998 } |
| 1983 } | 1999 } |
| 1984 | 2000 |
| 1985 | 2001 |
| 1986 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 2002 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 1987 Register object = ToRegister(instr->InputAt(0)); | 2003 Register object = ToRegister(instr->InputAt(0)); |
| 1988 Register result = ToRegister(instr->result()); | 2004 Register result = ToRegister(instr->result()); |
| 1989 if (instr->hydrogen()->is_in_object()) { | 2005 if (instr->hydrogen()->is_in_object()) { |
| 1990 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); | 2006 __ movq(result, FieldOperand(object, instr->hydrogen()->offset())); |
| 1991 } else { | 2007 } else { |
| (...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2287 __ movq(result, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 2303 __ movq(result, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 2288 __ movq(result, FieldOperand(result, GlobalObject::kGlobalReceiverOffset)); | 2304 __ movq(result, FieldOperand(result, GlobalObject::kGlobalReceiverOffset)); |
| 2289 } | 2305 } |
| 2290 | 2306 |
| 2291 | 2307 |
| 2292 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, | 2308 void LCodeGen::CallKnownFunction(Handle<JSFunction> function, |
| 2293 int arity, | 2309 int arity, |
| 2294 LInstruction* instr) { | 2310 LInstruction* instr) { |
| 2295 // Change context if needed. | 2311 // Change context if needed. |
| 2296 bool change_context = | 2312 bool change_context = |
| 2297 (graph()->info()->closure()->context() != function->context()) || | 2313 (info()->closure()->context() != function->context()) || |
| 2298 scope()->contains_with() || | 2314 scope()->contains_with() || |
| 2299 (scope()->num_heap_slots() > 0); | 2315 (scope()->num_heap_slots() > 0); |
| 2300 if (change_context) { | 2316 if (change_context) { |
| 2301 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); | 2317 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); |
| 2302 } | 2318 } |
| 2303 | 2319 |
| 2304 // Set rax to arguments count if adaption is not needed. Assumes that rax | 2320 // Set rax to arguments count if adaption is not needed. Assumes that rax |
| 2305 // is available to write to at this point. | 2321 // is available to write to at this point. |
| 2306 if (!function->NeedsArgumentsAdaption()) { | 2322 if (!function->NeedsArgumentsAdaption()) { |
| 2307 __ Set(rax, arity); | 2323 __ Set(rax, arity); |
| 2308 } | 2324 } |
| 2309 | 2325 |
| 2310 LPointerMap* pointers = instr->pointer_map(); | 2326 LPointerMap* pointers = instr->pointer_map(); |
| 2311 RecordPosition(pointers->position()); | 2327 RecordPosition(pointers->position()); |
| 2312 | 2328 |
| 2313 // Invoke function. | 2329 // Invoke function. |
| 2314 if (*function == *graph()->info()->closure()) { | 2330 if (*function == *info()->closure()) { |
| 2315 __ CallSelf(); | 2331 __ CallSelf(); |
| 2316 } else { | 2332 } else { |
| 2317 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); | 2333 __ call(FieldOperand(rdi, JSFunction::kCodeEntryOffset)); |
| 2318 } | 2334 } |
| 2319 | 2335 |
| 2320 // Setup deoptimization. | 2336 // Setup deoptimization. |
| 2321 RegisterLazyDeoptimization(instr); | 2337 RegisterLazyDeoptimization(instr); |
| 2322 | 2338 |
| 2323 // Restore context. | 2339 // Restore context. |
| 2324 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 2340 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
| (...skipping 1328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3653 RegisterEnvironmentForDeoptimization(environment); | 3669 RegisterEnvironmentForDeoptimization(environment); |
| 3654 ASSERT(osr_pc_offset_ == -1); | 3670 ASSERT(osr_pc_offset_ == -1); |
| 3655 osr_pc_offset_ = masm()->pc_offset(); | 3671 osr_pc_offset_ = masm()->pc_offset(); |
| 3656 } | 3672 } |
| 3657 | 3673 |
| 3658 #undef __ | 3674 #undef __ |
| 3659 | 3675 |
| 3660 } } // namespace v8::internal | 3676 } } // namespace v8::internal |
| 3661 | 3677 |
| 3662 #endif // V8_TARGET_ARCH_X64 | 3678 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |