Revision f230a1cf deps/v8/src/mips/macro-assembler-mips.cc

View differences:

deps/v8/src/mips/macro-assembler-mips.cc
35 35
#include "codegen.h"
36 36
#include "cpu-profiler.h"
37 37
#include "debug.h"
38
#include "isolate-inl.h"
38 39
#include "runtime.h"
39 40

  
40 41
namespace v8 {
......
248 249
                                 SmiCheck smi_check) {
249 250
  ASSERT(!AreAliased(object, address, value, t8));
250 251
  ASSERT(!AreAliased(object, address, value, t9));
251
  // The compiled code assumes that record write doesn't change the
252
  // context register, so we check that none of the clobbered
253
  // registers are cp.
254
  ASSERT(!address.is(cp) && !value.is(cp));
255 252

  
256 253
  if (emit_debug_code()) {
257 254
    lw(at, MemOperand(address));
......
3220 3217
                               Register dst,
3221 3218
                               Register length,
3222 3219
                               Register scratch) {
3223
  Label align_loop, align_loop_1, word_loop, byte_loop, byte_loop_1, done;
3220
  Label align_loop_1, word_loop, byte_loop, byte_loop_1, done;
3224 3221

  
3225 3222
  // Align src before copying in word size chunks.
3226
  bind(&align_loop);
3227
  Branch(&done, eq, length, Operand(zero_reg));
3223
  Branch(&byte_loop, le, length, Operand(kPointerSize));
3228 3224
  bind(&align_loop_1);
3229 3225
  And(scratch, src, kPointerSize - 1);
3230 3226
  Branch(&word_loop, eq, scratch, Operand(zero_reg));
......
3233 3229
  sb(scratch, MemOperand(dst));
3234 3230
  Addu(dst, dst, 1);
3235 3231
  Subu(length, length, Operand(1));
3236
  Branch(&byte_loop_1, ne, length, Operand(zero_reg));
3232
  Branch(&align_loop_1, ne, length, Operand(zero_reg));
3237 3233

  
3238 3234
  // Copy bytes in word size chunks.
3239 3235
  bind(&word_loop);
......
3847 3843
}
3848 3844

  
3849 3845

  
3850
void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
3851
                                              Address function_address,
3852
                                              ExternalReference thunk_ref,
3853
                                              Register thunk_last_arg,
3854
                                              int stack_space,
3855
                                              int return_value_offset_from_fp) {
3846
void MacroAssembler::CallApiFunctionAndReturn(
3847
    ExternalReference function,
3848
    Address function_address,
3849
    ExternalReference thunk_ref,
3850
    Register thunk_last_arg,
3851
    int stack_space,
3852
    MemOperand return_value_operand,
3853
    MemOperand* context_restore_operand) {
3856 3854
  ExternalReference next_address =
3857 3855
      ExternalReference::handle_scope_next_address(isolate());
3858 3856
  const int kNextOffset = 0;
......
3915 3913
  }
3916 3914

  
3917 3915
  Label promote_scheduled_exception;
3916
  Label exception_handled;
3918 3917
  Label delete_allocated_handles;
3919 3918
  Label leave_exit_frame;
3920 3919
  Label return_value_loaded;
3921 3920

  
3922 3921
  // Load value from ReturnValue.
3923
  lw(v0, MemOperand(fp, return_value_offset_from_fp*kPointerSize));
3922
  lw(v0, return_value_operand);
3924 3923
  bind(&return_value_loaded);
3925 3924

  
3926 3925
  // No more valid handles (the result handle was the last one). Restore
......
3941 3940
  li(at, Operand(ExternalReference::scheduled_exception_address(isolate())));
3942 3941
  lw(t1, MemOperand(at));
3943 3942
  Branch(&promote_scheduled_exception, ne, t0, Operand(t1));
3943
  bind(&exception_handled);
3944

  
3945
  bool restore_context = context_restore_operand != NULL;
3946
  if (restore_context) {
3947
    lw(cp, *context_restore_operand);
3948
  }
3944 3949
  li(s0, Operand(stack_space));
3945
  LeaveExitFrame(false, s0, true);
3950
  LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN);
3946 3951

  
3947 3952
  bind(&promote_scheduled_exception);
3948
  TailCallExternalReference(
3949
      ExternalReference(Runtime::kPromoteScheduledException, isolate()),
3950
      0,
3951
      1);
3953
  {
3954
    FrameScope frame(this, StackFrame::INTERNAL);
3955
    CallExternalReference(
3956
        ExternalReference(Runtime::kPromoteScheduledException, isolate()),
3957
        0);
3958
  }
3959
  jmp(&exception_handled);
3952 3960

  
3953 3961
  // HandleScope limit has changed. Delete allocated extensions.
3954 3962
  bind(&delete_allocated_handles);
......
4125 4133

  
4126 4134

  
4127 4135
void MacroAssembler::CallRuntime(const Runtime::Function* f,
4128
                                 int num_arguments) {
4136
                                 int num_arguments,
4137
                                 SaveFPRegsMode save_doubles) {
4129 4138
  // All parameters are on the stack. v0 has the return value after call.
4130 4139

  
4131 4140
  // If the expected number of arguments of the runtime function is
......
4142 4151
  // smarter.
4143 4152
  PrepareCEntryArgs(num_arguments);
4144 4153
  PrepareCEntryFunction(ExternalReference(f, isolate()));
4145
  CEntryStub stub(1);
4146
  CallStub(&stub);
4147
}
4148

  
4149

  
4150
void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
4151
  const Runtime::Function* function = Runtime::FunctionForId(id);
4152
  PrepareCEntryArgs(function->nargs);
4153
  PrepareCEntryFunction(ExternalReference(function, isolate()));
4154
  CEntryStub stub(1, kSaveFPRegs);
4154
  CEntryStub stub(1, save_doubles);
4155 4155
  CallStub(&stub);
4156 4156
}
4157 4157

  
4158 4158

  
4159
void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
4160
  CallRuntime(Runtime::FunctionForId(fid), num_arguments);
4161
}
4162

  
4163

  
4164 4159
void MacroAssembler::CallExternalReference(const ExternalReference& ext,
4165 4160
                                           int num_arguments,
4166 4161
                                           BranchDelaySlot bd) {
......
4591 4586
}
4592 4587

  
4593 4588

  
4589
void MacroAssembler::Prologue(PrologueFrameMode frame_mode) {
4590
  if (frame_mode == BUILD_STUB_FRAME) {
4591
    Push(ra, fp, cp);
4592
    Push(Smi::FromInt(StackFrame::STUB));
4593
    // Adjust FP to point to saved FP.
4594
    Addu(fp, sp, Operand(2 * kPointerSize));
4595
  } else {
4596
    PredictableCodeSizeScope predictible_code_size_scope(
4597
      this, kNoCodeAgeSequenceLength * Assembler::kInstrSize);
4598
    // The following three instructions must remain together and unmodified
4599
    // for code aging to work properly.
4600
    if (isolate()->IsCodePreAgingActive()) {
4601
      // Pre-age the code.
4602
      Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
4603
      nop(Assembler::CODE_AGE_MARKER_NOP);
4604
      // Save the function's original return address
4605
      // (it will be clobbered by Call(t9))
4606
      mov(at, ra);
4607
      // Load the stub address to t9 and call it
4608
      li(t9,
4609
         Operand(reinterpret_cast<uint32_t>(stub->instruction_start())));
4610
      Call(t9);
4611
      // Record the stub address in the empty space for GetCodeAgeAndParity()
4612
      dd(reinterpret_cast<uint32_t>(stub->instruction_start()));
4613
    } else {
4614
      Push(ra, fp, cp, a1);
4615
      nop(Assembler::CODE_AGE_SEQUENCE_NOP);
4616
      // Adjust fp to point to caller's fp.
4617
      Addu(fp, sp, Operand(2 * kPointerSize));
4618
    }
4619
  }
4620
}
4621

  
4622

  
4594 4623
void MacroAssembler::EnterFrame(StackFrame::Type type) {
4595 4624
  addiu(sp, sp, -5 * kPointerSize);
4596 4625
  li(t8, Operand(Smi::FromInt(type)));
......
4684 4713

  
4685 4714
void MacroAssembler::LeaveExitFrame(bool save_doubles,
4686 4715
                                    Register argument_count,
4716
                                    bool restore_context,
4687 4717
                                    bool do_return) {
4688 4718
  // Optionally restore all double registers.
4689 4719
  if (save_doubles) {
......
4700 4730
  sw(zero_reg, MemOperand(t8));
4701 4731

  
4702 4732
  // Restore current context from top and clear it in debug mode.
4703
  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
4704
  lw(cp, MemOperand(t8));
4733
  if (restore_context) {
4734
    li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
4735
    lw(cp, MemOperand(t8));
4736
  }
4705 4737
#ifdef DEBUG
4738
  li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
4706 4739
  sw(a3, MemOperand(t8));
4707 4740
#endif
4708 4741

  
......
4929 4962
}
4930 4963

  
4931 4964

  
4965
void MacroAssembler::LookupNumberStringCache(Register object,
4966
                                             Register result,
4967
                                             Register scratch1,
4968
                                             Register scratch2,
4969
                                             Register scratch3,
4970
                                             Label* not_found) {
4971
  // Use of registers. Register result is used as a temporary.
4972
  Register number_string_cache = result;
4973
  Register mask = scratch3;
4974

  
4975
  // Load the number string cache.
4976
  LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
4977

  
4978
  // Make the hash mask from the length of the number string cache. It
4979
  // contains two elements (number and string) for each cache entry.
4980
  lw(mask, FieldMemOperand(number_string_cache, FixedArray::kLengthOffset));
4981
  // Divide length by two (length is a smi).
4982
  sra(mask, mask, kSmiTagSize + 1);
4983
  Addu(mask, mask, -1);  // Make mask.
4984

  
4985
  // Calculate the entry in the number string cache. The hash value in the
4986
  // number string cache for smis is just the smi value, and the hash for
4987
  // doubles is the xor of the upper and lower words. See
4988
  // Heap::GetNumberStringCache.
4989
  Label is_smi;
4990
  Label load_result_from_cache;
4991
  JumpIfSmi(object, &is_smi);
4992
  CheckMap(object,
4993
           scratch1,
4994
           Heap::kHeapNumberMapRootIndex,
4995
           not_found,
4996
           DONT_DO_SMI_CHECK);
4997

  
4998
  STATIC_ASSERT(8 == kDoubleSize);
4999
  Addu(scratch1,
5000
       object,
5001
       Operand(HeapNumber::kValueOffset - kHeapObjectTag));
5002
  lw(scratch2, MemOperand(scratch1, kPointerSize));
5003
  lw(scratch1, MemOperand(scratch1, 0));
5004
  Xor(scratch1, scratch1, Operand(scratch2));
5005
  And(scratch1, scratch1, Operand(mask));
5006

  
5007
  // Calculate address of entry in string cache: each entry consists
5008
  // of two pointer sized fields.
5009
  sll(scratch1, scratch1, kPointerSizeLog2 + 1);
5010
  Addu(scratch1, number_string_cache, scratch1);
5011

  
5012
  Register probe = mask;
5013
  lw(probe, FieldMemOperand(scratch1, FixedArray::kHeaderSize));
5014
  JumpIfSmi(probe, not_found);
5015
  ldc1(f12, FieldMemOperand(object, HeapNumber::kValueOffset));
5016
  ldc1(f14, FieldMemOperand(probe, HeapNumber::kValueOffset));
5017
  BranchF(&load_result_from_cache, NULL, eq, f12, f14);
5018
  Branch(not_found);
5019

  
5020
  bind(&is_smi);
5021
  Register scratch = scratch1;
5022
  sra(scratch, object, 1);   // Shift away the tag.
5023
  And(scratch, mask, Operand(scratch));
5024

  
5025
  // Calculate address of entry in string cache: each entry consists
5026
  // of two pointer sized fields.
5027
  sll(scratch, scratch, kPointerSizeLog2 + 1);
5028
  Addu(scratch, number_string_cache, scratch);
5029

  
5030
  // Check if the entry is the smi we are looking for.
5031
  lw(probe, FieldMemOperand(scratch, FixedArray::kHeaderSize));
5032
  Branch(not_found, ne, object, Operand(probe));
5033

  
5034
  // Get the result from the cache.
5035
  bind(&load_result_from_cache);
5036
  lw(result, FieldMemOperand(scratch, FixedArray::kHeaderSize + kPointerSize));
5037

  
5038
  IncrementCounter(isolate()->counters()->number_to_string_native(),
5039
                   1,
5040
                   scratch1,
5041
                   scratch2);
5042
}
5043

  
5044

  
4932 5045
void MacroAssembler::JumpIfNonSmisNotBothSequentialAsciiStrings(
4933 5046
    Register first,
4934 5047
    Register second,
......
5492 5605
void MacroAssembler::TestJSArrayForAllocationMemento(
5493 5606
    Register receiver_reg,
5494 5607
    Register scratch_reg,
5608
    Label* no_memento_found,
5495 5609
    Condition cond,
5496 5610
    Label* allocation_memento_present) {
5497
  Label no_memento_available;
5498 5611
  ExternalReference new_space_start =
5499 5612
      ExternalReference::new_space_start(isolate());
5500 5613
  ExternalReference new_space_allocation_top =
5501 5614
      ExternalReference::new_space_allocation_top_address(isolate());
5502 5615
  Addu(scratch_reg, receiver_reg,
5503 5616
       Operand(JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
5504
  Branch(&no_memento_available, lt, scratch_reg, Operand(new_space_start));
5617
  Branch(no_memento_found, lt, scratch_reg, Operand(new_space_start));
5505 5618
  li(at, Operand(new_space_allocation_top));
5506 5619
  lw(at, MemOperand(at));
5507
  Branch(&no_memento_available, gt, scratch_reg, Operand(at));
5620
  Branch(no_memento_found, gt, scratch_reg, Operand(at));
5508 5621
  lw(scratch_reg, MemOperand(scratch_reg, -AllocationMemento::kSize));
5509
  Branch(allocation_memento_present, cond, scratch_reg,
5510
      Operand(Handle<Map>(isolate()->heap()->allocation_memento_map())));
5511
  bind(&no_memento_available);
5622
  if (allocation_memento_present) {
5623
    Branch(allocation_memento_present, cond, scratch_reg,
5624
           Operand(isolate()->factory()->allocation_memento_map()));
5625
  }
5512 5626
}
5513 5627

  
5514 5628

  

Also available in: Unified diff