| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 __ b(eq, &ok); | 126 __ b(eq, &ok); |
| 127 int receiver_offset = scope()->num_parameters() * kPointerSize; | 127 int receiver_offset = scope()->num_parameters() * kPointerSize; |
| 128 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 128 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| 129 __ str(r2, MemOperand(sp, receiver_offset)); | 129 __ str(r2, MemOperand(sp, receiver_offset)); |
| 130 __ bind(&ok); | 130 __ bind(&ok); |
| 131 } | 131 } |
| 132 } | 132 } |
| 133 | 133 |
| 134 info()->set_prologue_offset(masm_->pc_offset()); | 134 info()->set_prologue_offset(masm_->pc_offset()); |
| 135 if (NeedsEagerFrame()) { | 135 if (NeedsEagerFrame()) { |
| 136 if (info()->IsStub()) { | 136 __ Prologue(info()->IsStub() ? BUILD_STUB_FRAME : BUILD_FUNCTION_FRAME); |
| 137 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | |
| 138 __ Push(Smi::FromInt(StackFrame::STUB)); | |
| 139 // Adjust FP to point to saved FP. | |
| 140 __ add(fp, sp, Operand(2 * kPointerSize)); | |
| 141 } else { | |
| 142 PredictableCodeSizeScope predictible_code_size_scope( | |
| 143 masm_, kNoCodeAgeSequenceLength * Assembler::kInstrSize); | |
| 144 // The following three instructions must remain together and unmodified | |
| 145 // for code aging to work properly. | |
| 146 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | |
| 147 __ nop(ip.code()); | |
| 148 // Adjust FP to point to saved FP. | |
| 149 __ add(fp, sp, Operand(2 * kPointerSize)); | |
| 150 } | |
| 151 frame_is_built_ = true; | 137 frame_is_built_ = true; |
| 152 info_->AddNoFrameRange(0, masm_->pc_offset()); | 138 info_->AddNoFrameRange(0, masm_->pc_offset()); |
| 153 } | 139 } |
| 154 | 140 |
| 155 // Reserve space for the stack slots needed by the code. | 141 // Reserve space for the stack slots needed by the code. |
| 156 int slots = GetStackSlotCount(); | 142 int slots = GetStackSlotCount(); |
| 157 if (slots > 0) { | 143 if (slots > 0) { |
| 158 if (FLAG_debug_code) { | 144 if (FLAG_debug_code) { |
| 159 __ sub(sp, sp, Operand(slots * kPointerSize)); | 145 __ sub(sp, sp, Operand(slots * kPointerSize)); |
| 160 __ push(r0); | 146 __ push(r0); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 __ sub(sp, sp, Operand(slots * kPointerSize)); | 238 __ sub(sp, sp, Operand(slots * kPointerSize)); |
| 253 } | 239 } |
| 254 | 240 |
| 255 | 241 |
| 256 bool LCodeGen::GenerateDeferredCode() { | 242 bool LCodeGen::GenerateDeferredCode() { |
| 257 ASSERT(is_generating()); | 243 ASSERT(is_generating()); |
| 258 if (deferred_.length() > 0) { | 244 if (deferred_.length() > 0) { |
| 259 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 245 for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { |
| 260 LDeferredCode* code = deferred_[i]; | 246 LDeferredCode* code = deferred_[i]; |
| 261 | 247 |
| 262 int pos = instructions_->at(code->instruction_index())->position(); | 248 HValue* value = |
| 263 RecordAndUpdatePosition(pos); | 249 instructions_->at(code->instruction_index())->hydrogen_value(); |
| 250 RecordAndWritePosition(value->position()); |
| 264 | 251 |
| 265 Comment(";;; <@%d,#%d> " | 252 Comment(";;; <@%d,#%d> " |
| 266 "-------------------- Deferred %s --------------------", | 253 "-------------------- Deferred %s --------------------", |
| 267 code->instruction_index(), | 254 code->instruction_index(), |
| 268 code->instr()->hydrogen_value()->id(), | 255 code->instr()->hydrogen_value()->id(), |
| 269 code->instr()->Mnemonic()); | 256 code->instr()->Mnemonic()); |
| 270 __ bind(code->entry()); | 257 __ bind(code->entry()); |
| 271 if (NeedsDeferredFrame()) { | 258 if (NeedsDeferredFrame()) { |
| 272 Comment(";;; Build frame"); | 259 Comment(";;; Build frame"); |
| 273 ASSERT(!frame_is_built_); | 260 ASSERT(!frame_is_built_); |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 665 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
| 679 RelocInfo::Mode mode, | 666 RelocInfo::Mode mode, |
| 680 LInstruction* instr, | 667 LInstruction* instr, |
| 681 SafepointMode safepoint_mode, | 668 SafepointMode safepoint_mode, |
| 682 TargetAddressStorageMode storage_mode) { | 669 TargetAddressStorageMode storage_mode) { |
| 683 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 670 EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); |
| 684 ASSERT(instr != NULL); | 671 ASSERT(instr != NULL); |
| 685 // Block literal pool emission to ensure nop indicating no inlined smi code | 672 // Block literal pool emission to ensure nop indicating no inlined smi code |
| 686 // is in the correct position. | 673 // is in the correct position. |
| 687 Assembler::BlockConstPoolScope block_const_pool(masm()); | 674 Assembler::BlockConstPoolScope block_const_pool(masm()); |
| 688 LPointerMap* pointers = instr->pointer_map(); | |
| 689 RecordPosition(pointers->position()); | |
| 690 __ Call(code, mode, TypeFeedbackId::None(), al, storage_mode); | 675 __ Call(code, mode, TypeFeedbackId::None(), al, storage_mode); |
| 691 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 676 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
| 692 | 677 |
| 693 // Signal that we don't inline smi code before these stubs in the | 678 // Signal that we don't inline smi code before these stubs in the |
| 694 // optimizing code generator. | 679 // optimizing code generator. |
| 695 if (code->kind() == Code::BINARY_OP_IC || | 680 if (code->kind() == Code::BINARY_OP_IC || |
| 696 code->kind() == Code::COMPARE_IC) { | 681 code->kind() == Code::COMPARE_IC) { |
| 697 __ nop(); | 682 __ nop(); |
| 698 } | 683 } |
| 699 } | 684 } |
| 700 | 685 |
| 701 | 686 |
| 702 void LCodeGen::CallRuntime(const Runtime::Function* function, | 687 void LCodeGen::CallRuntime(const Runtime::Function* function, |
| 703 int num_arguments, | 688 int num_arguments, |
| 704 LInstruction* instr, | 689 LInstruction* instr, |
| 705 SaveFPRegsMode save_doubles) { | 690 SaveFPRegsMode save_doubles) { |
| 706 ASSERT(instr != NULL); | 691 ASSERT(instr != NULL); |
| 707 LPointerMap* pointers = instr->pointer_map(); | |
| 708 ASSERT(pointers != NULL); | |
| 709 RecordPosition(pointers->position()); | |
| 710 | 692 |
| 711 __ CallRuntime(function, num_arguments, save_doubles); | 693 __ CallRuntime(function, num_arguments, save_doubles); |
| 712 | 694 |
| 713 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 695 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
| 714 } | 696 } |
| 715 | 697 |
| 716 | 698 |
| 717 void LCodeGen::LoadContextFromDeferred(LOperand* context) { | 699 void LCodeGen::LoadContextFromDeferred(LOperand* context) { |
| 718 if (context->IsRegister()) { | 700 if (context->IsRegister()) { |
| 719 __ Move(cp, ToRegister(context)); | 701 __ Move(cp, ToRegister(context)); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 957 } | 939 } |
| 958 | 940 |
| 959 | 941 |
| 960 void LCodeGen::RecordSafepoint(LPointerMap* pointers, | 942 void LCodeGen::RecordSafepoint(LPointerMap* pointers, |
| 961 Safepoint::DeoptMode deopt_mode) { | 943 Safepoint::DeoptMode deopt_mode) { |
| 962 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); | 944 RecordSafepoint(pointers, Safepoint::kSimple, 0, deopt_mode); |
| 963 } | 945 } |
| 964 | 946 |
| 965 | 947 |
| 966 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { | 948 void LCodeGen::RecordSafepoint(Safepoint::DeoptMode deopt_mode) { |
| 967 LPointerMap empty_pointers(RelocInfo::kNoPosition, zone()); | 949 LPointerMap empty_pointers(zone()); |
| 968 RecordSafepoint(&empty_pointers, deopt_mode); | 950 RecordSafepoint(&empty_pointers, deopt_mode); |
| 969 } | 951 } |
| 970 | 952 |
| 971 | 953 |
| 972 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, | 954 void LCodeGen::RecordSafepointWithRegisters(LPointerMap* pointers, |
| 973 int arguments, | 955 int arguments, |
| 974 Safepoint::DeoptMode deopt_mode) { | 956 Safepoint::DeoptMode deopt_mode) { |
| 975 RecordSafepoint( | 957 RecordSafepoint( |
| 976 pointers, Safepoint::kWithRegisters, arguments, deopt_mode); | 958 pointers, Safepoint::kWithRegisters, arguments, deopt_mode); |
| 977 } | 959 } |
| 978 | 960 |
| 979 | 961 |
| 980 void LCodeGen::RecordSafepointWithRegistersAndDoubles( | 962 void LCodeGen::RecordSafepointWithRegistersAndDoubles( |
| 981 LPointerMap* pointers, | 963 LPointerMap* pointers, |
| 982 int arguments, | 964 int arguments, |
| 983 Safepoint::DeoptMode deopt_mode) { | 965 Safepoint::DeoptMode deopt_mode) { |
| 984 RecordSafepoint( | 966 RecordSafepoint( |
| 985 pointers, Safepoint::kWithRegistersAndDoubles, arguments, deopt_mode); | 967 pointers, Safepoint::kWithRegistersAndDoubles, arguments, deopt_mode); |
| 986 } | 968 } |
| 987 | 969 |
| 988 | 970 |
| 989 void LCodeGen::RecordPosition(int position) { | 971 void LCodeGen::RecordAndWritePosition(int position) { |
| 990 if (position == RelocInfo::kNoPosition) return; | 972 if (position == RelocInfo::kNoPosition) return; |
| 991 masm()->positions_recorder()->RecordPosition(position); | 973 masm()->positions_recorder()->RecordPosition(position); |
| 974 masm()->positions_recorder()->WriteRecordedPositions(); |
| 992 } | 975 } |
| 993 | 976 |
| 994 | 977 |
| 995 void LCodeGen::RecordAndUpdatePosition(int position) { | |
| 996 if (position >= 0 && position != old_position_) { | |
| 997 masm()->positions_recorder()->RecordPosition(position); | |
| 998 old_position_ = position; | |
| 999 } | |
| 1000 } | |
| 1001 | |
| 1002 | |
| 1003 static const char* LabelType(LLabel* label) { | 978 static const char* LabelType(LLabel* label) { |
| 1004 if (label->is_loop_header()) return " (loop header)"; | 979 if (label->is_loop_header()) return " (loop header)"; |
| 1005 if (label->is_osr_entry()) return " (OSR entry)"; | 980 if (label->is_osr_entry()) return " (OSR entry)"; |
| 1006 return ""; | 981 return ""; |
| 1007 } | 982 } |
| 1008 | 983 |
| 1009 | 984 |
| 1010 void LCodeGen::DoLabel(LLabel* label) { | 985 void LCodeGen::DoLabel(LLabel* label) { |
| 1011 Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------", | 986 Comment(";;; <@%d,#%d> -------------------- B%d%s --------------------", |
| 1012 current_instruction_, | 987 current_instruction_, |
| (...skipping 1316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2329 } | 2304 } |
| 2330 | 2305 |
| 2331 | 2306 |
| 2332 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { | 2307 Condition LCodeGen::TokenToCondition(Token::Value op, bool is_unsigned) { |
| 2333 Condition cond = kNoCondition; | 2308 Condition cond = kNoCondition; |
| 2334 switch (op) { | 2309 switch (op) { |
| 2335 case Token::EQ: | 2310 case Token::EQ: |
| 2336 case Token::EQ_STRICT: | 2311 case Token::EQ_STRICT: |
| 2337 cond = eq; | 2312 cond = eq; |
| 2338 break; | 2313 break; |
| 2314 case Token::NE: |
| 2315 case Token::NE_STRICT: |
| 2316 cond = ne; |
| 2317 break; |
| 2339 case Token::LT: | 2318 case Token::LT: |
| 2340 cond = is_unsigned ? lo : lt; | 2319 cond = is_unsigned ? lo : lt; |
| 2341 break; | 2320 break; |
| 2342 case Token::GT: | 2321 case Token::GT: |
| 2343 cond = is_unsigned ? hi : gt; | 2322 cond = is_unsigned ? hi : gt; |
| 2344 break; | 2323 break; |
| 2345 case Token::LTE: | 2324 case Token::LTE: |
| 2346 cond = is_unsigned ? ls : le; | 2325 cond = is_unsigned ? ls : le; |
| 2347 break; | 2326 break; |
| 2348 case Token::GTE: | 2327 case Token::GTE: |
| (...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3496 __ b(eq, &invoke); | 3475 __ b(eq, &invoke); |
| 3497 __ bind(&loop); | 3476 __ bind(&loop); |
| 3498 __ ldr(scratch, MemOperand(elements, length, LSL, 2)); | 3477 __ ldr(scratch, MemOperand(elements, length, LSL, 2)); |
| 3499 __ push(scratch); | 3478 __ push(scratch); |
| 3500 __ sub(length, length, Operand(1), SetCC); | 3479 __ sub(length, length, Operand(1), SetCC); |
| 3501 __ b(ne, &loop); | 3480 __ b(ne, &loop); |
| 3502 | 3481 |
| 3503 __ bind(&invoke); | 3482 __ bind(&invoke); |
| 3504 ASSERT(instr->HasPointerMap()); | 3483 ASSERT(instr->HasPointerMap()); |
| 3505 LPointerMap* pointers = instr->pointer_map(); | 3484 LPointerMap* pointers = instr->pointer_map(); |
| 3506 RecordPosition(pointers->position()); | |
| 3507 SafepointGenerator safepoint_generator( | 3485 SafepointGenerator safepoint_generator( |
| 3508 this, pointers, Safepoint::kLazyDeopt); | 3486 this, pointers, Safepoint::kLazyDeopt); |
| 3509 // The number of arguments is stored in receiver which is r0, as expected | 3487 // The number of arguments is stored in receiver which is r0, as expected |
| 3510 // by InvokeFunction. | 3488 // by InvokeFunction. |
| 3511 ParameterCount actual(receiver); | 3489 ParameterCount actual(receiver); |
| 3512 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3490 __ InvokeFunction(function, actual, CALL_FUNCTION, |
| 3513 safepoint_generator, CALL_AS_METHOD); | 3491 safepoint_generator, CALL_AS_METHOD); |
| 3514 } | 3492 } |
| 3515 | 3493 |
| 3516 | 3494 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3586 int arity, | 3564 int arity, |
| 3587 LInstruction* instr, | 3565 LInstruction* instr, |
| 3588 CallKind call_kind, | 3566 CallKind call_kind, |
| 3589 R1State r1_state) { | 3567 R1State r1_state) { |
| 3590 bool dont_adapt_arguments = | 3568 bool dont_adapt_arguments = |
| 3591 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; | 3569 formal_parameter_count == SharedFunctionInfo::kDontAdaptArgumentsSentinel; |
| 3592 bool can_invoke_directly = | 3570 bool can_invoke_directly = |
| 3593 dont_adapt_arguments || formal_parameter_count == arity; | 3571 dont_adapt_arguments || formal_parameter_count == arity; |
| 3594 | 3572 |
| 3595 LPointerMap* pointers = instr->pointer_map(); | 3573 LPointerMap* pointers = instr->pointer_map(); |
| 3596 RecordPosition(pointers->position()); | |
| 3597 | 3574 |
| 3598 if (can_invoke_directly) { | 3575 if (can_invoke_directly) { |
| 3599 if (r1_state == R1_UNINITIALIZED) { | 3576 if (r1_state == R1_UNINITIALIZED) { |
| 3600 __ LoadHeapObject(r1, function); | 3577 __ LoadHeapObject(r1, function); |
| 3601 } | 3578 } |
| 3602 | 3579 |
| 3603 // Change context. | 3580 // Change context. |
| 3604 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 3581 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 3605 | 3582 |
| 3606 // Set r0 to arguments count if adaption is not needed. Assumes that r0 | 3583 // Set r0 to arguments count if adaption is not needed. Assumes that r0 |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3998 | 3975 |
| 3999 | 3976 |
| 4000 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 3977 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
| 4001 ASSERT(ToRegister(instr->context()).is(cp)); | 3978 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4002 ASSERT(ToRegister(instr->function()).is(r1)); | 3979 ASSERT(ToRegister(instr->function()).is(r1)); |
| 4003 ASSERT(instr->HasPointerMap()); | 3980 ASSERT(instr->HasPointerMap()); |
| 4004 | 3981 |
| 4005 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 3982 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
| 4006 if (known_function.is_null()) { | 3983 if (known_function.is_null()) { |
| 4007 LPointerMap* pointers = instr->pointer_map(); | 3984 LPointerMap* pointers = instr->pointer_map(); |
| 4008 RecordPosition(pointers->position()); | |
| 4009 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3985 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
| 4010 ParameterCount count(instr->arity()); | 3986 ParameterCount count(instr->arity()); |
| 4011 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 3987 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
| 4012 } else { | 3988 } else { |
| 4013 CallKnownFunction(known_function, | 3989 CallKnownFunction(known_function, |
| 4014 instr->hydrogen()->formal_parameter_count(), | 3990 instr->hydrogen()->formal_parameter_count(), |
| 4015 instr->arity(), | 3991 instr->arity(), |
| 4016 instr, | 3992 instr, |
| 4017 CALL_AS_METHOD, | 3993 CALL_AS_METHOD, |
| 4018 R1_CONTAINS_TARGET); | 3994 R1_CONTAINS_TARGET); |
| (...skipping 510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4529 RecordSafepointWithRegistersAndDoubles( | 4505 RecordSafepointWithRegistersAndDoubles( |
| 4530 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); | 4506 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); |
| 4531 } | 4507 } |
| 4532 __ bind(¬_applicable); | 4508 __ bind(¬_applicable); |
| 4533 } | 4509 } |
| 4534 | 4510 |
| 4535 | 4511 |
| 4536 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4512 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4537 Register object = ToRegister(instr->object()); | 4513 Register object = ToRegister(instr->object()); |
| 4538 Register temp = ToRegister(instr->temp()); | 4514 Register temp = ToRegister(instr->temp()); |
| 4539 __ TestJSArrayForAllocationMemento(object, temp); | 4515 Label no_memento_found; |
| 4516 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
| 4540 DeoptimizeIf(eq, instr->environment()); | 4517 DeoptimizeIf(eq, instr->environment()); |
| 4518 __ bind(&no_memento_found); |
| 4541 } | 4519 } |
| 4542 | 4520 |
| 4543 | 4521 |
| 4544 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4522 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4545 ASSERT(ToRegister(instr->context()).is(cp)); | 4523 ASSERT(ToRegister(instr->context()).is(cp)); |
| 4546 __ push(ToRegister(instr->left())); | 4524 __ push(ToRegister(instr->left())); |
| 4547 __ push(ToRegister(instr->right())); | 4525 __ push(ToRegister(instr->right())); |
| 4548 StringAddStub stub(instr->hydrogen()->flags()); | 4526 StringAddStub stub(instr->hydrogen()->flags()); |
| 4549 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4527 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 4550 } | 4528 } |
| (...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4963 __ adc(scratch2, input_reg, Operand(input_reg)); | 4941 __ adc(scratch2, input_reg, Operand(input_reg)); |
| 4964 | 4942 |
| 4965 // Heap number map check. | 4943 // Heap number map check. |
| 4966 __ ldr(scratch1, FieldMemOperand(scratch2, HeapObject::kMapOffset)); | 4944 __ ldr(scratch1, FieldMemOperand(scratch2, HeapObject::kMapOffset)); |
| 4967 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4945 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
| 4968 __ cmp(scratch1, Operand(ip)); | 4946 __ cmp(scratch1, Operand(ip)); |
| 4969 | 4947 |
| 4970 if (instr->truncating()) { | 4948 if (instr->truncating()) { |
| 4971 // Performs a truncating conversion of a floating point number as used by | 4949 // Performs a truncating conversion of a floating point number as used by |
| 4972 // the JS bitwise operations. | 4950 // the JS bitwise operations. |
| 4973 Label heap_number; | 4951 Label no_heap_number, check_bools, check_false; |
| 4974 __ b(eq, &heap_number); | 4952 __ b(ne, &no_heap_number); |
| 4975 // Check for undefined. Undefined is converted to zero for truncating | 4953 __ TruncateHeapNumberToI(input_reg, scratch2); |
| 4976 // conversions. | 4954 __ b(&done); |
| 4955 |
| 4956 // Check for Oddballs. Undefined/False is converted to zero and True to one |
| 4957 // for truncating conversions. |
| 4958 __ bind(&no_heap_number); |
| 4977 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4959 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
| 4978 __ cmp(scratch2, Operand(ip)); | 4960 __ cmp(scratch2, Operand(ip)); |
| 4961 __ b(ne, &check_bools); |
| 4962 __ mov(input_reg, Operand::Zero()); |
| 4963 __ b(&done); |
| 4964 |
| 4965 __ bind(&check_bools); |
| 4966 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 4967 __ cmp(scratch2, Operand(ip)); |
| 4968 __ b(ne, &check_false); |
| 4969 __ mov(input_reg, Operand(1)); |
| 4970 __ b(&done); |
| 4971 |
| 4972 __ bind(&check_false); |
| 4973 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
| 4974 __ cmp(scratch2, Operand(ip)); |
| 4979 DeoptimizeIf(ne, instr->environment()); | 4975 DeoptimizeIf(ne, instr->environment()); |
| 4980 __ mov(input_reg, Operand::Zero()); | 4976 __ mov(input_reg, Operand::Zero()); |
| 4981 __ b(&done); | 4977 __ b(&done); |
| 4982 | |
| 4983 __ bind(&heap_number); | |
| 4984 __ TruncateHeapNumberToI(input_reg, scratch2); | |
| 4985 } else { | 4978 } else { |
| 4986 // Deoptimize if we don't have a heap number. | 4979 // Deoptimize if we don't have a heap number. |
| 4987 DeoptimizeIf(ne, instr->environment()); | 4980 DeoptimizeIf(ne, instr->environment()); |
| 4988 | 4981 |
| 4989 __ sub(ip, scratch2, Operand(kHeapObjectTag)); | 4982 __ sub(ip, scratch2, Operand(kHeapObjectTag)); |
| 4990 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset); | 4983 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset); |
| 4991 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch); | 4984 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch); |
| 4992 DeoptimizeIf(ne, instr->environment()); | 4985 DeoptimizeIf(ne, instr->environment()); |
| 4993 | 4986 |
| 4994 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4987 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| (...skipping 831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5826 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5819 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5827 __ ldr(result, FieldMemOperand(scratch, | 5820 __ ldr(result, FieldMemOperand(scratch, |
| 5828 FixedArray::kHeaderSize - kPointerSize)); | 5821 FixedArray::kHeaderSize - kPointerSize)); |
| 5829 __ bind(&done); | 5822 __ bind(&done); |
| 5830 } | 5823 } |
| 5831 | 5824 |
| 5832 | 5825 |
| 5833 #undef __ | 5826 #undef __ |
| 5834 | 5827 |
| 5835 } } // namespace v8::internal | 5828 } } // namespace v8::internal |
| OLD | NEW |