| 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 1545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1556 } | 1556 } |
| 1557 | 1557 |
| 1558 | 1558 |
| 1559 void MacroAssembler::Branch(Label* L, Condition cond, Register rs, | 1559 void MacroAssembler::Branch(Label* L, Condition cond, Register rs, |
| 1560 const Operand& rt, | 1560 const Operand& rt, |
| 1561 BranchDelaySlot bdslot) { | 1561 BranchDelaySlot bdslot) { |
| 1562 if (L->is_bound()) { | 1562 if (L->is_bound()) { |
| 1563 if (is_near(L)) { | 1563 if (is_near(L)) { |
| 1564 BranchShort(L, cond, rs, rt, bdslot); | 1564 BranchShort(L, cond, rs, rt, bdslot); |
| 1565 } else { | 1565 } else { |
| 1566 Label skip; | 1566 if (cond != cc_always) { |
| 1567 Condition neg_cond = NegateCondition(cond); | 1567 Label skip; |
| 1568 BranchShort(&skip, neg_cond, rs, rt); | 1568 Condition neg_cond = NegateCondition(cond); |
| 1569 Jr(L, bdslot); | 1569 BranchShort(&skip, neg_cond, rs, rt); |
| 1570 bind(&skip); | 1570 Jr(L, bdslot); |
| 1571 bind(&skip); |
| 1572 } else { |
| 1573 Jr(L, bdslot); |
| 1574 } |
| 1571 } | 1575 } |
| 1572 } else { | 1576 } else { |
| 1573 if (is_trampoline_emitted()) { | 1577 if (is_trampoline_emitted()) { |
| 1574 Label skip; | 1578 if (cond != cc_always) { |
| 1575 Condition neg_cond = NegateCondition(cond); | 1579 Label skip; |
| 1576 BranchShort(&skip, neg_cond, rs, rt); | 1580 Condition neg_cond = NegateCondition(cond); |
| 1577 Jr(L, bdslot); | 1581 BranchShort(&skip, neg_cond, rs, rt); |
| 1578 bind(&skip); | 1582 Jr(L, bdslot); |
| 1583 bind(&skip); |
| 1584 } else { |
| 1585 Jr(L, bdslot); |
| 1586 } |
| 1579 } else { | 1587 } else { |
| 1580 BranchShort(L, cond, rs, rt, bdslot); | 1588 BranchShort(L, cond, rs, rt, bdslot); |
| 1581 } | 1589 } |
| 1582 } | 1590 } |
| 1583 } | 1591 } |
| 1584 | 1592 |
| 1585 | 1593 |
| 1586 void MacroAssembler::Branch(Label* L, | 1594 void MacroAssembler::Branch(Label* L, |
| 1587 Condition cond, | 1595 Condition cond, |
| 1588 Register rs, | 1596 Register rs, |
| (...skipping 1248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2837 JumpToHandlerEntry(); | 2845 JumpToHandlerEntry(); |
| 2838 } | 2846 } |
| 2839 | 2847 |
| 2840 | 2848 |
| 2841 void MacroAssembler::Allocate(int object_size, | 2849 void MacroAssembler::Allocate(int object_size, |
| 2842 Register result, | 2850 Register result, |
| 2843 Register scratch1, | 2851 Register scratch1, |
| 2844 Register scratch2, | 2852 Register scratch2, |
| 2845 Label* gc_required, | 2853 Label* gc_required, |
| 2846 AllocationFlags flags) { | 2854 AllocationFlags flags) { |
| 2847 ASSERT(object_size <= Page::kMaxNonCodeHeapObjectSize); | 2855 ASSERT(object_size <= Page::kMaxRegularHeapObjectSize); |
| 2848 if (!FLAG_inline_new) { | 2856 if (!FLAG_inline_new) { |
| 2849 if (emit_debug_code()) { | 2857 if (emit_debug_code()) { |
| 2850 // Trash the registers to simulate an allocation failure. | 2858 // Trash the registers to simulate an allocation failure. |
| 2851 li(result, 0x7091); | 2859 li(result, 0x7091); |
| 2852 li(scratch1, 0x7191); | 2860 li(scratch1, 0x7191); |
| 2853 li(scratch2, 0x7291); | 2861 li(scratch2, 0x7291); |
| 2854 } | 2862 } |
| 2855 jmp(gc_required); | 2863 jmp(gc_required); |
| 2856 return; | 2864 return; |
| 2857 } | 2865 } |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3424 jmp(&done); | 3432 jmp(&done); |
| 3425 | 3433 |
| 3426 bind(&maybe_nan); | 3434 bind(&maybe_nan); |
| 3427 // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise | 3435 // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise |
| 3428 // it's an Infinity, and the non-NaN code path applies. | 3436 // it's an Infinity, and the non-NaN code path applies. |
| 3429 Branch(&is_nan, gt, exponent_reg, Operand(scratch1)); | 3437 Branch(&is_nan, gt, exponent_reg, Operand(scratch1)); |
| 3430 lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); | 3438 lw(mantissa_reg, FieldMemOperand(value_reg, HeapNumber::kMantissaOffset)); |
| 3431 Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg)); | 3439 Branch(&have_double_value, eq, mantissa_reg, Operand(zero_reg)); |
| 3432 bind(&is_nan); | 3440 bind(&is_nan); |
| 3433 // Load canonical NaN for storing into the double array. | 3441 // Load canonical NaN for storing into the double array. |
| 3434 uint64_t nan_int64 = BitCast<uint64_t>( | 3442 LoadRoot(at, Heap::kNanValueRootIndex); |
| 3435 FixedDoubleArray::canonical_not_the_hole_nan_as_double()); | 3443 lw(mantissa_reg, FieldMemOperand(at, HeapNumber::kMantissaOffset)); |
| 3436 li(mantissa_reg, Operand(static_cast<uint32_t>(nan_int64))); | 3444 lw(exponent_reg, FieldMemOperand(at, HeapNumber::kExponentOffset)); |
| 3437 li(exponent_reg, Operand(static_cast<uint32_t>(nan_int64 >> 32))); | |
| 3438 jmp(&have_double_value); | 3445 jmp(&have_double_value); |
| 3439 | 3446 |
| 3440 bind(&smi_value); | 3447 bind(&smi_value); |
| 3441 Addu(scratch1, elements_reg, | 3448 Addu(scratch1, elements_reg, |
| 3442 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag - | 3449 Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag - |
| 3443 elements_offset)); | 3450 elements_offset)); |
| 3444 sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize); | 3451 sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize); |
| 3445 Addu(scratch1, scratch1, scratch2); | 3452 Addu(scratch1, scratch1, scratch2); |
| 3446 // scratch1 is now effective address of the double element | 3453 // scratch1 is now effective address of the double element |
| 3447 | 3454 |
| (...skipping 417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3865 Jump(stub->GetCode(isolate()), RelocInfo::CODE_TARGET, cond, r1, r2, bd); | 3872 Jump(stub->GetCode(isolate()), RelocInfo::CODE_TARGET, cond, r1, r2, bd); |
| 3866 } | 3873 } |
| 3867 | 3874 |
| 3868 | 3875 |
| 3869 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 3876 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
| 3870 return ref0.address() - ref1.address(); | 3877 return ref0.address() - ref1.address(); |
| 3871 } | 3878 } |
| 3872 | 3879 |
| 3873 | 3880 |
| 3874 void MacroAssembler::CallApiFunctionAndReturn( | 3881 void MacroAssembler::CallApiFunctionAndReturn( |
| 3875 ExternalReference function, | 3882 Register function_address, |
| 3876 Address function_address, | |
| 3877 ExternalReference thunk_ref, | 3883 ExternalReference thunk_ref, |
| 3878 Register thunk_last_arg, | |
| 3879 int stack_space, | 3884 int stack_space, |
| 3880 MemOperand return_value_operand, | 3885 MemOperand return_value_operand, |
| 3881 MemOperand* context_restore_operand) { | 3886 MemOperand* context_restore_operand) { |
| 3882 ExternalReference next_address = | 3887 ExternalReference next_address = |
| 3883 ExternalReference::handle_scope_next_address(isolate()); | 3888 ExternalReference::handle_scope_next_address(isolate()); |
| 3884 const int kNextOffset = 0; | 3889 const int kNextOffset = 0; |
| 3885 const int kLimitOffset = AddressOffset( | 3890 const int kLimitOffset = AddressOffset( |
| 3886 ExternalReference::handle_scope_limit_address(isolate()), | 3891 ExternalReference::handle_scope_limit_address(isolate()), |
| 3887 next_address); | 3892 next_address); |
| 3888 const int kLevelOffset = AddressOffset( | 3893 const int kLevelOffset = AddressOffset( |
| 3889 ExternalReference::handle_scope_level_address(isolate()), | 3894 ExternalReference::handle_scope_level_address(isolate()), |
| 3890 next_address); | 3895 next_address); |
| 3891 | 3896 |
| 3897 ASSERT(function_address.is(a1) || function_address.is(a2)); |
| 3898 |
| 3899 Label profiler_disabled; |
| 3900 Label end_profiler_check; |
| 3901 bool* is_profiling_flag = |
| 3902 isolate()->cpu_profiler()->is_profiling_address(); |
| 3903 STATIC_ASSERT(sizeof(*is_profiling_flag) == 1); |
| 3904 li(t9, reinterpret_cast<int32_t>(is_profiling_flag)); |
| 3905 lb(t9, MemOperand(t9, 0)); |
| 3906 Branch(&profiler_disabled, eq, t9, Operand(zero_reg)); |
| 3907 |
| 3908 // Additional parameter is the address of the actual callback. |
| 3909 li(t9, Operand(thunk_ref)); |
| 3910 jmp(&end_profiler_check); |
| 3911 |
| 3912 bind(&profiler_disabled); |
| 3913 mov(t9, function_address); |
| 3914 bind(&end_profiler_check); |
| 3915 |
| 3892 // Allocate HandleScope in callee-save registers. | 3916 // Allocate HandleScope in callee-save registers. |
| 3893 li(s3, Operand(next_address)); | 3917 li(s3, Operand(next_address)); |
| 3894 lw(s0, MemOperand(s3, kNextOffset)); | 3918 lw(s0, MemOperand(s3, kNextOffset)); |
| 3895 lw(s1, MemOperand(s3, kLimitOffset)); | 3919 lw(s1, MemOperand(s3, kLimitOffset)); |
| 3896 lw(s2, MemOperand(s3, kLevelOffset)); | 3920 lw(s2, MemOperand(s3, kLevelOffset)); |
| 3897 Addu(s2, s2, Operand(1)); | 3921 Addu(s2, s2, Operand(1)); |
| 3898 sw(s2, MemOperand(s3, kLevelOffset)); | 3922 sw(s2, MemOperand(s3, kLevelOffset)); |
| 3899 | 3923 |
| 3900 if (FLAG_log_timer_events) { | 3924 if (FLAG_log_timer_events) { |
| 3901 FrameScope frame(this, StackFrame::MANUAL); | 3925 FrameScope frame(this, StackFrame::MANUAL); |
| 3902 PushSafepointRegisters(); | 3926 PushSafepointRegisters(); |
| 3903 PrepareCallCFunction(1, a0); | 3927 PrepareCallCFunction(1, a0); |
| 3904 li(a0, Operand(ExternalReference::isolate_address(isolate()))); | 3928 li(a0, Operand(ExternalReference::isolate_address(isolate()))); |
| 3905 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); | 3929 CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1); |
| 3906 PopSafepointRegisters(); | 3930 PopSafepointRegisters(); |
| 3907 } | 3931 } |
| 3908 | 3932 |
| 3909 Label profiler_disabled; | |
| 3910 Label end_profiler_check; | |
| 3911 bool* is_profiling_flag = | |
| 3912 isolate()->cpu_profiler()->is_profiling_address(); | |
| 3913 STATIC_ASSERT(sizeof(*is_profiling_flag) == 1); | |
| 3914 li(t9, reinterpret_cast<int32_t>(is_profiling_flag)); | |
| 3915 lb(t9, MemOperand(t9, 0)); | |
| 3916 beq(t9, zero_reg, &profiler_disabled); | |
| 3917 | |
| 3918 // Third parameter is the address of the actual getter function. | |
| 3919 li(thunk_last_arg, reinterpret_cast<int32_t>(function_address)); | |
| 3920 li(t9, Operand(thunk_ref)); | |
| 3921 jmp(&end_profiler_check); | |
| 3922 | |
| 3923 bind(&profiler_disabled); | |
| 3924 li(t9, Operand(function)); | |
| 3925 | |
| 3926 bind(&end_profiler_check); | |
| 3927 | |
| 3928 // Native call returns to the DirectCEntry stub which redirects to the | 3933 // Native call returns to the DirectCEntry stub which redirects to the |
| 3929 // return address pushed on stack (could have moved after GC). | 3934 // return address pushed on stack (could have moved after GC). |
| 3930 // DirectCEntry stub itself is generated early and never moves. | 3935 // DirectCEntry stub itself is generated early and never moves. |
| 3931 DirectCEntryStub stub; | 3936 DirectCEntryStub stub; |
| 3932 stub.GenerateCall(this, t9); | 3937 stub.GenerateCall(this, t9); |
| 3933 | 3938 |
| 3934 if (FLAG_log_timer_events) { | 3939 if (FLAG_log_timer_events) { |
| 3935 FrameScope frame(this, StackFrame::MANUAL); | 3940 FrameScope frame(this, StackFrame::MANUAL); |
| 3936 PushSafepointRegisters(); | 3941 PushSafepointRegisters(); |
| 3937 PrepareCallCFunction(1, a0); | 3942 PrepareCallCFunction(1, a0); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4334 Branch(&L, cc, rs, rt); | 4339 Branch(&L, cc, rs, rt); |
| 4335 Abort(reason); | 4340 Abort(reason); |
| 4336 // Will not return here. | 4341 // Will not return here. |
| 4337 bind(&L); | 4342 bind(&L); |
| 4338 } | 4343 } |
| 4339 | 4344 |
| 4340 | 4345 |
| 4341 void MacroAssembler::Abort(BailoutReason reason) { | 4346 void MacroAssembler::Abort(BailoutReason reason) { |
| 4342 Label abort_start; | 4347 Label abort_start; |
| 4343 bind(&abort_start); | 4348 bind(&abort_start); |
| 4344 // We want to pass the msg string like a smi to avoid GC | 4349 #ifdef DEBUG |
| 4345 // problems, however msg is not guaranteed to be aligned | |
| 4346 // properly. Instead, we pass an aligned pointer that is | |
| 4347 // a proper v8 smi, but also pass the alignment difference | |
| 4348 // from the real pointer as a smi. | |
| 4349 const char* msg = GetBailoutReason(reason); | 4350 const char* msg = GetBailoutReason(reason); |
| 4350 intptr_t p1 = reinterpret_cast<intptr_t>(msg); | |
| 4351 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag; | |
| 4352 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi()); | |
| 4353 #ifdef DEBUG | |
| 4354 if (msg != NULL) { | 4351 if (msg != NULL) { |
| 4355 RecordComment("Abort message: "); | 4352 RecordComment("Abort message: "); |
| 4356 RecordComment(msg); | 4353 RecordComment(msg); |
| 4357 } | 4354 } |
| 4358 | 4355 |
| 4359 if (FLAG_trap_on_abort) { | 4356 if (FLAG_trap_on_abort) { |
| 4360 stop(msg); | 4357 stop(msg); |
| 4361 return; | 4358 return; |
| 4362 } | 4359 } |
| 4363 #endif | 4360 #endif |
| 4364 | 4361 |
| 4365 li(a0, Operand(p0)); | 4362 li(a0, Operand(Smi::FromInt(reason))); |
| 4366 push(a0); | |
| 4367 li(a0, Operand(Smi::FromInt(p1 - p0))); | |
| 4368 push(a0); | 4363 push(a0); |
| 4369 // Disable stub call restrictions to always allow calls to abort. | 4364 // Disable stub call restrictions to always allow calls to abort. |
| 4370 if (!has_frame_) { | 4365 if (!has_frame_) { |
| 4371 // We don't actually want to generate a pile of code for this, so just | 4366 // We don't actually want to generate a pile of code for this, so just |
| 4372 // claim there is a stack frame, without generating one. | 4367 // claim there is a stack frame, without generating one. |
| 4373 FrameScope scope(this, StackFrame::NONE); | 4368 FrameScope scope(this, StackFrame::NONE); |
| 4374 CallRuntime(Runtime::kAbort, 2); | 4369 CallRuntime(Runtime::kAbort, 1); |
| 4375 } else { | 4370 } else { |
| 4376 CallRuntime(Runtime::kAbort, 2); | 4371 CallRuntime(Runtime::kAbort, 1); |
| 4377 } | 4372 } |
| 4378 // Will not return here. | 4373 // Will not return here. |
| 4379 if (is_trampoline_pool_blocked()) { | 4374 if (is_trampoline_pool_blocked()) { |
| 4380 // If the calling code cares about the exact number of | 4375 // If the calling code cares about the exact number of |
| 4381 // instructions generated, we insert padding here to keep the size | 4376 // instructions generated, we insert padding here to keep the size |
| 4382 // of the Abort macro constant. | 4377 // of the Abort macro constant. |
| 4383 // Currently in debug mode with debug_code enabled the number of | 4378 // Currently in debug mode with debug_code enabled the number of |
| 4384 // generated instructions is 14, so we use this as a maximum value. | 4379 // generated instructions is 10, so we use this as a maximum value. |
| 4385 static const int kExpectedAbortInstructions = 14; | 4380 static const int kExpectedAbortInstructions = 10; |
| 4386 int abort_instructions = InstructionsGeneratedSince(&abort_start); | 4381 int abort_instructions = InstructionsGeneratedSince(&abort_start); |
| 4387 ASSERT(abort_instructions <= kExpectedAbortInstructions); | 4382 ASSERT(abort_instructions <= kExpectedAbortInstructions); |
| 4388 while (abort_instructions++ < kExpectedAbortInstructions) { | 4383 while (abort_instructions++ < kExpectedAbortInstructions) { |
| 4389 nop(); | 4384 nop(); |
| 4390 } | 4385 } |
| 4391 } | 4386 } |
| 4392 } | 4387 } |
| 4393 | 4388 |
| 4394 | 4389 |
| 4395 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { | 4390 void MacroAssembler::LoadContext(Register dst, int context_chain_length) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4428 lw(at, FieldMemOperand(scratch, offset)); | 4423 lw(at, FieldMemOperand(scratch, offset)); |
| 4429 Branch(no_map_match, ne, map_in_out, Operand(at)); | 4424 Branch(no_map_match, ne, map_in_out, Operand(at)); |
| 4430 | 4425 |
| 4431 // Use the transitioned cached map. | 4426 // Use the transitioned cached map. |
| 4432 offset = transitioned_kind * kPointerSize + | 4427 offset = transitioned_kind * kPointerSize + |
| 4433 FixedArrayBase::kHeaderSize; | 4428 FixedArrayBase::kHeaderSize; |
| 4434 lw(map_in_out, FieldMemOperand(scratch, offset)); | 4429 lw(map_in_out, FieldMemOperand(scratch, offset)); |
| 4435 } | 4430 } |
| 4436 | 4431 |
| 4437 | 4432 |
| 4438 void MacroAssembler::LoadInitialArrayMap( | |
| 4439 Register function_in, Register scratch, | |
| 4440 Register map_out, bool can_have_holes) { | |
| 4441 ASSERT(!function_in.is(map_out)); | |
| 4442 Label done; | |
| 4443 lw(map_out, FieldMemOperand(function_in, | |
| 4444 JSFunction::kPrototypeOrInitialMapOffset)); | |
| 4445 if (!FLAG_smi_only_arrays) { | |
| 4446 ElementsKind kind = can_have_holes ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; | |
| 4447 LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | |
| 4448 kind, | |
| 4449 map_out, | |
| 4450 scratch, | |
| 4451 &done); | |
| 4452 } else if (can_have_holes) { | |
| 4453 LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, | |
| 4454 FAST_HOLEY_SMI_ELEMENTS, | |
| 4455 map_out, | |
| 4456 scratch, | |
| 4457 &done); | |
| 4458 } | |
| 4459 bind(&done); | |
| 4460 } | |
| 4461 | |
| 4462 | |
| 4463 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 4433 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
| 4464 // Load the global or builtins object from the current context. | 4434 // Load the global or builtins object from the current context. |
| 4465 lw(function, | 4435 lw(function, |
| 4466 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 4436 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
| 4467 // Load the native context from the global or builtins object. | 4437 // Load the native context from the global or builtins object. |
| 4468 lw(function, FieldMemOperand(function, | 4438 lw(function, FieldMemOperand(function, |
| 4469 GlobalObject::kNativeContextOffset)); | 4439 GlobalObject::kNativeContextOffset)); |
| 4470 // Load the function from the native context. | 4440 // Load the function from the native context. |
| 4471 lw(function, MemOperand(function, Context::SlotOffset(index))); | 4441 lw(function, MemOperand(function, Context::SlotOffset(index))); |
| 4472 } | 4442 } |
| 4473 | 4443 |
| 4474 | 4444 |
| 4475 void MacroAssembler::LoadArrayFunction(Register function) { | |
| 4476 // Load the global or builtins object from the current context. | |
| 4477 lw(function, | |
| 4478 MemOperand(cp, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | |
| 4479 // Load the global context from the global or builtins object. | |
| 4480 lw(function, | |
| 4481 FieldMemOperand(function, GlobalObject::kGlobalContextOffset)); | |
| 4482 // Load the array function from the native context. | |
| 4483 lw(function, | |
| 4484 MemOperand(function, Context::SlotOffset(Context::ARRAY_FUNCTION_INDEX))); | |
| 4485 } | |
| 4486 | |
| 4487 | |
| 4488 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 4445 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
| 4489 Register map, | 4446 Register map, |
| 4490 Register scratch) { | 4447 Register scratch) { |
| 4491 // Load the initial map. The global functions all have initial maps. | 4448 // Load the initial map. The global functions all have initial maps. |
| 4492 lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 4449 lw(map, FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 4493 if (emit_debug_code()) { | 4450 if (emit_debug_code()) { |
| 4494 Label ok, fail; | 4451 Label ok, fail; |
| 4495 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); | 4452 CheckMap(map, scratch, Heap::kMetaMapRootIndex, &fail, DO_SMI_CHECK); |
| 4496 Branch(&ok); | 4453 Branch(&ok); |
| 4497 bind(&fail); | 4454 bind(&fail); |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5043 } | 5000 } |
| 5044 | 5001 |
| 5045 | 5002 |
| 5046 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, | 5003 void MacroAssembler::EmitSeqStringSetCharCheck(Register string, |
| 5047 Register index, | 5004 Register index, |
| 5048 Register value, | 5005 Register value, |
| 5049 Register scratch, | 5006 Register scratch, |
| 5050 uint32_t encoding_mask) { | 5007 uint32_t encoding_mask) { |
| 5051 Label is_object; | 5008 Label is_object; |
| 5052 SmiTst(string, at); | 5009 SmiTst(string, at); |
| 5053 ThrowIf(eq, kNonObject, at, Operand(zero_reg)); | 5010 Check(ne, kNonObject, at, Operand(zero_reg)); |
| 5054 | 5011 |
| 5055 lw(at, FieldMemOperand(string, HeapObject::kMapOffset)); | 5012 lw(at, FieldMemOperand(string, HeapObject::kMapOffset)); |
| 5056 lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset)); | 5013 lbu(at, FieldMemOperand(at, Map::kInstanceTypeOffset)); |
| 5057 | 5014 |
| 5058 andi(at, at, kStringRepresentationMask | kStringEncodingMask); | 5015 andi(at, at, kStringRepresentationMask | kStringEncodingMask); |
| 5059 li(scratch, Operand(encoding_mask)); | 5016 li(scratch, Operand(encoding_mask)); |
| 5060 ThrowIf(ne, kUnexpectedStringType, at, Operand(scratch)); | 5017 Check(eq, kUnexpectedStringType, at, Operand(scratch)); |
| 5061 | 5018 |
| 5062 // The index is assumed to be untagged coming in, tag it to compare with the | 5019 // The index is assumed to be untagged coming in, tag it to compare with the |
| 5063 // string length without using a temp register, it is restored at the end of | 5020 // string length without using a temp register, it is restored at the end of |
| 5064 // this function. | 5021 // this function. |
| 5065 Label index_tag_ok, index_tag_bad; | 5022 Label index_tag_ok, index_tag_bad; |
| 5066 TrySmiTag(index, scratch, &index_tag_bad); | 5023 TrySmiTag(index, scratch, &index_tag_bad); |
| 5067 Branch(&index_tag_ok); | 5024 Branch(&index_tag_ok); |
| 5068 bind(&index_tag_bad); | 5025 bind(&index_tag_bad); |
| 5069 Throw(kIndexIsTooLarge); | 5026 Abort(kIndexIsTooLarge); |
| 5070 bind(&index_tag_ok); | 5027 bind(&index_tag_ok); |
| 5071 | 5028 |
| 5072 lw(at, FieldMemOperand(string, String::kLengthOffset)); | 5029 lw(at, FieldMemOperand(string, String::kLengthOffset)); |
| 5073 ThrowIf(ge, kIndexIsTooLarge, index, Operand(at)); | 5030 Check(lt, kIndexIsTooLarge, index, Operand(at)); |
| 5074 | 5031 |
| 5075 ASSERT(Smi::FromInt(0) == 0); | 5032 ASSERT(Smi::FromInt(0) == 0); |
| 5076 ThrowIf(lt, kIndexIsNegative, index, Operand(zero_reg)); | 5033 Check(ge, kIndexIsNegative, index, Operand(zero_reg)); |
| 5077 | 5034 |
| 5078 SmiUntag(index, index); | 5035 SmiUntag(index, index); |
| 5079 } | 5036 } |
| 5080 | 5037 |
| 5081 | 5038 |
| 5082 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, | 5039 void MacroAssembler::PrepareCallCFunction(int num_reg_arguments, |
| 5083 int num_double_arguments, | 5040 int num_double_arguments, |
| 5084 Register scratch) { | 5041 Register scratch) { |
| 5085 int frame_alignment = ActivationFrameAlignment(); | 5042 int frame_alignment = ActivationFrameAlignment(); |
| 5086 | 5043 |
| (...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5547 | 5504 |
| 5548 bind(&next); | 5505 bind(&next); |
| 5549 lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); | 5506 lw(a1, FieldMemOperand(a2, HeapObject::kMapOffset)); |
| 5550 | 5507 |
| 5551 // For all objects but the receiver, check that the cache is empty. | 5508 // For all objects but the receiver, check that the cache is empty. |
| 5552 EnumLength(a3, a1); | 5509 EnumLength(a3, a1); |
| 5553 Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0))); | 5510 Branch(call_runtime, ne, a3, Operand(Smi::FromInt(0))); |
| 5554 | 5511 |
| 5555 bind(&start); | 5512 bind(&start); |
| 5556 | 5513 |
| 5557 // Check that there are no elements. Register r2 contains the current JS | 5514 // Check that there are no elements. Register a2 contains the current JS |
| 5558 // object we've reached through the prototype chain. | 5515 // object we've reached through the prototype chain. |
| 5516 Label no_elements; |
| 5559 lw(a2, FieldMemOperand(a2, JSObject::kElementsOffset)); | 5517 lw(a2, FieldMemOperand(a2, JSObject::kElementsOffset)); |
| 5560 Branch(call_runtime, ne, a2, Operand(empty_fixed_array_value)); | 5518 Branch(&no_elements, eq, a2, Operand(empty_fixed_array_value)); |
| 5561 | 5519 |
| 5520 // Second chance, the object may be using the empty slow element dictionary. |
| 5521 LoadRoot(at, Heap::kEmptySlowElementDictionaryRootIndex); |
| 5522 Branch(call_runtime, ne, a2, Operand(at)); |
| 5523 |
| 5524 bind(&no_elements); |
| 5562 lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); | 5525 lw(a2, FieldMemOperand(a1, Map::kPrototypeOffset)); |
| 5563 Branch(&next, ne, a2, Operand(null_value)); | 5526 Branch(&next, ne, a2, Operand(null_value)); |
| 5564 } | 5527 } |
| 5565 | 5528 |
| 5566 | 5529 |
| 5567 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { | 5530 void MacroAssembler::ClampUint8(Register output_reg, Register input_reg) { |
| 5568 ASSERT(!output_reg.is(input_reg)); | 5531 ASSERT(!output_reg.is(input_reg)); |
| 5569 Label done; | 5532 Label done; |
| 5570 li(output_reg, Operand(255)); | 5533 li(output_reg, Operand(255)); |
| 5571 // Normal branch: nop in delay slot. | 5534 // Normal branch: nop in delay slot. |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5739 opcode == BGTZL); | 5702 opcode == BGTZL); |
| 5740 opcode = (cond == eq) ? BEQ : BNE; | 5703 opcode = (cond == eq) ? BEQ : BNE; |
| 5741 instr = (instr & ~kOpcodeMask) | opcode; | 5704 instr = (instr & ~kOpcodeMask) | opcode; |
| 5742 masm_.emit(instr); | 5705 masm_.emit(instr); |
| 5743 } | 5706 } |
| 5744 | 5707 |
| 5745 | 5708 |
| 5746 } } // namespace v8::internal | 5709 } } // namespace v8::internal |
| 5747 | 5710 |
| 5748 #endif // V8_TARGET_ARCH_MIPS | 5711 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |