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

View differences:

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

  
......
232 233
  j(not_equal, &done, Label::kNear);
233 234

  
234 235
  sub(esp, Immediate(kDoubleSize));
235
  movdbl(MemOperand(esp, 0), input_reg);
236
  movsd(MemOperand(esp, 0), input_reg);
236 237
  SlowTruncateToI(result_reg, esp, 0);
237 238
  add(esp, Immediate(kDoubleSize));
238 239
  bind(&done);
......
253 254
                               Label::Distance dst) {
254 255
  Label done;
255 256
  sub(esp, Immediate(kPointerSize));
256
  fist_s(MemOperand(esp, 0));
257 257
  fld(0);
258
  fist_s(MemOperand(esp, 0));
258 259
  fild_s(MemOperand(esp, 0));
259 260
  pop(result_reg);
260 261
  FCmp();
......
283 284
                               Label::Distance dst) {
284 285
  ASSERT(!input_reg.is(scratch));
285 286
  cvttsd2si(result_reg, Operand(input_reg));
286
  cvtsi2sd(scratch, Operand(result_reg));
287
  Cvtsi2sd(scratch, Operand(result_reg));
287 288
  ucomisd(scratch, input_reg);
288 289
  j(not_equal, conversion_failed, dst);
289 290
  j(parity_even, conversion_failed, dst);  // NaN.
......
344 345
    }
345 346
  } else if (CpuFeatures::IsSupported(SSE2)) {
346 347
    CpuFeatureScope scope(this, SSE2);
347
    movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
348
    movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
348 349
    cvttsd2si(result_reg, Operand(xmm0));
349 350
    cmp(result_reg, 0x80000000u);
350 351
    j(not_equal, &done, Label::kNear);
......
361 362
    if (input_reg.is(result_reg)) {
362 363
      // Input is clobbered. Restore number from double scratch.
363 364
      sub(esp, Immediate(kDoubleSize));
364
      movdbl(MemOperand(esp, 0), xmm0);
365
      movsd(MemOperand(esp, 0), xmm0);
365 366
      SlowTruncateToI(result_reg, esp, 0);
366 367
      add(esp, Immediate(kDoubleSize));
367 368
    } else {
......
390 391
    ASSERT(!temp.is(no_xmm_reg));
391 392
    CpuFeatureScope scope(this, SSE2);
392 393

  
393
    movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
394
    movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
394 395
    cvttsd2si(result_reg, Operand(xmm0));
395
    cvtsi2sd(temp, Operand(result_reg));
396
    Cvtsi2sd(temp, Operand(result_reg));
396 397
    ucomisd(xmm0, temp);
397 398
    RecordComment("Deferred TaggedToI: lost precision");
398 399
    j(not_equal, lost_precision, Label::kNear);
......
445 446
}
446 447

  
447 448

  
448

  
449
static double kUint32Bias =
450
    static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1;
451

  
452

  
453 449
void MacroAssembler::LoadUint32(XMMRegister dst,
454 450
                                Register src,
455 451
                                XMMRegister scratch) {
456 452
  Label done;
457 453
  cmp(src, Immediate(0));
458
  movdbl(scratch,
459
         Operand(reinterpret_cast<int32_t>(&kUint32Bias), RelocInfo::NONE32));
460
  cvtsi2sd(dst, src);
454
  ExternalReference uint32_bias =
455
        ExternalReference::address_of_uint32_bias();
456
  movsd(scratch, Operand::StaticVariable(uint32_bias));
457
  Cvtsi2sd(dst, src);
461 458
  j(not_sign, &done, Label::kNear);
462 459
  addsd(dst, scratch);
463 460
  bind(&done);
464 461
}
465 462

  
466 463

  
464
void MacroAssembler::LoadUint32NoSSE2(Register src) {
465
  Label done;
466
  push(src);
467
  fild_s(Operand(esp, 0));
468
  cmp(src, Immediate(0));
469
  j(not_sign, &done, Label::kNear);
470
  ExternalReference uint32_bias =
471
        ExternalReference::address_of_uint32_bias();
472
  fld_d(Operand::StaticVariable(uint32_bias));
473
  faddp(1);
474
  bind(&done);
475
  add(esp, Immediate(kPointerSize));
476
}
477

  
478

  
467 479
void MacroAssembler::RecordWriteArray(Register object,
468 480
                                      Register value,
469 481
                                      Register index,
......
676 688
#endif
677 689

  
678 690

  
691
void MacroAssembler::Cvtsi2sd(XMMRegister dst, const Operand& src) {
692
  xorps(dst, dst);
693
  cvtsi2sd(dst, src);
694
}
695

  
696

  
679 697
void MacroAssembler::Set(Register dst, const Immediate& x) {
680 698
  if (x.is_zero()) {
681 699
    xor_(dst, dst);  // Shorter than mov.
......
799 817
      ExternalReference::address_of_canonical_non_hole_nan();
800 818
  if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
801 819
    CpuFeatureScope use_sse2(this, SSE2);
802
    movdbl(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
820
    movsd(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset));
803 821
    bind(&have_double_value);
804
    movdbl(FieldOperand(elements, key, times_4,
822
    movsd(FieldOperand(elements, key, times_4,
805 823
                        FixedDoubleArray::kHeaderSize - elements_offset),
806 824
           scratch2);
807 825
  } else {
......
821 839
  bind(&is_nan);
822 840
  if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
823 841
    CpuFeatureScope use_sse2(this, SSE2);
824
    movdbl(scratch2, Operand::StaticVariable(canonical_nan_reference));
842
    movsd(scratch2, Operand::StaticVariable(canonical_nan_reference));
825 843
  } else {
826 844
    fld_d(Operand::StaticVariable(canonical_nan_reference));
827 845
  }
......
834 852
  SmiUntag(scratch1);
835 853
  if (CpuFeatures::IsSupported(SSE2) && specialize_for_processor) {
836 854
    CpuFeatureScope fscope(this, SSE2);
837
    cvtsi2sd(scratch2, scratch1);
838
    movdbl(FieldOperand(elements, key, times_4,
855
    Cvtsi2sd(scratch2, scratch1);
856
    movsd(FieldOperand(elements, key, times_4,
839 857
                        FixedDoubleArray::kHeaderSize - elements_offset),
840 858
           scratch2);
841 859
  } else {
......
996 1014
}
997 1015

  
998 1016

  
1017
void MacroAssembler::Prologue(PrologueFrameMode frame_mode) {
1018
  if (frame_mode == BUILD_STUB_FRAME) {
1019
    push(ebp);  // Caller's frame pointer.
1020
    mov(ebp, esp);
1021
    push(esi);  // Callee's context.
1022
    push(Immediate(Smi::FromInt(StackFrame::STUB)));
1023
  } else {
1024
    PredictableCodeSizeScope predictible_code_size_scope(this,
1025
        kNoCodeAgeSequenceLength);
1026
    if (isolate()->IsCodePreAgingActive()) {
1027
        // Pre-age the code.
1028
      call(isolate()->builtins()->MarkCodeAsExecutedOnce(),
1029
          RelocInfo::CODE_AGE_SEQUENCE);
1030
      Nop(kNoCodeAgeSequenceLength - Assembler::kCallInstructionLength);
1031
    } else {
1032
      push(ebp);  // Caller's frame pointer.
1033
      mov(ebp, esp);
1034
      push(esi);  // Callee's context.
1035
      push(edi);  // Callee's JS function.
1036
    }
1037
  }
1038
}
1039

  
1040

  
999 1041
void MacroAssembler::EnterFrame(StackFrame::Type type) {
1000 1042
  push(ebp);
1001 1043
  mov(ebp, esp);
......
1051 1093
    const int offset = -2 * kPointerSize;
1052 1094
    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
1053 1095
      XMMRegister reg = XMMRegister::from_code(i);
1054
      movdbl(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
1096
      movsd(Operand(ebp, offset - ((i + 1) * kDoubleSize)), reg);
1055 1097
    }
1056 1098
  } else {
1057 1099
    sub(esp, Immediate(argc * kPointerSize));
......
1095 1137
    const int offset = -2 * kPointerSize;
1096 1138
    for (int i = 0; i < XMMRegister::kNumRegisters; i++) {
1097 1139
      XMMRegister reg = XMMRegister::from_code(i);
1098
      movdbl(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
1140
      movsd(reg, Operand(ebp, offset - ((i + 1) * kDoubleSize)));
1099 1141
    }
1100 1142
  }
1101 1143

  
......
1109 1151
  // Push the return address to get ready to return.
1110 1152
  push(ecx);
1111 1153

  
1112
  LeaveExitFrameEpilogue();
1154
  LeaveExitFrameEpilogue(true);
1113 1155
}
1114 1156

  
1115 1157

  
1116
void MacroAssembler::LeaveExitFrameEpilogue() {
1158
void MacroAssembler::LeaveExitFrameEpilogue(bool restore_context) {
1117 1159
  // Restore current context from top and clear it in debug mode.
1118 1160
  ExternalReference context_address(Isolate::kContextAddress, isolate());
1119
  mov(esi, Operand::StaticVariable(context_address));
1161
  if (restore_context) {
1162
    mov(esi, Operand::StaticVariable(context_address));
1163
  }
1120 1164
#ifdef DEBUG
1121 1165
  mov(Operand::StaticVariable(context_address), Immediate(0));
1122 1166
#endif
......
1128 1172
}
1129 1173

  
1130 1174

  
1131
void MacroAssembler::LeaveApiExitFrame() {
1175
void MacroAssembler::LeaveApiExitFrame(bool restore_context) {
1132 1176
  mov(esp, ebp);
1133 1177
  pop(ebp);
1134 1178

  
1135
  LeaveExitFrameEpilogue();
1179
  LeaveExitFrameEpilogue(restore_context);
1136 1180
}
1137 1181

  
1138 1182

  
......
2141 2185
}
2142 2186

  
2143 2187

  
2144
void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
2145
  CallRuntime(Runtime::FunctionForId(id), num_arguments);
2146
}
2147

  
2148

  
2149
void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) {
2150
  const Runtime::Function* function = Runtime::FunctionForId(id);
2151
  Set(eax, Immediate(function->nargs));
2152
  mov(ebx, Immediate(ExternalReference(function, isolate())));
2153
  CEntryStub ces(1, CpuFeatures::IsSupported(SSE2) ? kSaveFPRegs
2154
                                                   : kDontSaveFPRegs);
2155
  CallStub(&ces);
2156
}
2157

  
2158

  
2159 2188
void MacroAssembler::CallRuntime(const Runtime::Function* f,
2160
                                 int num_arguments) {
2189
                                 int num_arguments,
2190
                                 SaveFPRegsMode save_doubles) {
2161 2191
  // If the expected number of arguments of the runtime function is
2162 2192
  // constant, we check that the actual number of arguments match the
2163 2193
  // expectation.
......
2172 2202
  // smarter.
2173 2203
  Set(eax, Immediate(num_arguments));
2174 2204
  mov(ebx, Immediate(ExternalReference(f, isolate())));
2175
  CEntryStub ces(1);
2205
  CEntryStub ces(1, CpuFeatures::IsSupported(SSE2) ? save_doubles
2206
                                                   : kDontSaveFPRegs);
2176 2207
  CallStub(&ces);
2177 2208
}
2178 2209

  
......
2221 2252
}
2222 2253

  
2223 2254

  
2224
void MacroAssembler::CallApiFunctionAndReturn(Address function_address,
2225
                                              Address thunk_address,
2226
                                              Operand thunk_last_arg,
2227
                                              int stack_space,
2228
                                              int return_value_offset) {
2255
void MacroAssembler::CallApiFunctionAndReturn(
2256
    Address function_address,
2257
    Address thunk_address,
2258
    Operand thunk_last_arg,
2259
    int stack_space,
2260
    Operand return_value_operand,
2261
    Operand* context_restore_operand) {
2229 2262
  ExternalReference next_address =
2230 2263
      ExternalReference::handle_scope_next_address(isolate());
2231 2264
  ExternalReference limit_address =
......
2281 2314

  
2282 2315
  Label prologue;
2283 2316
  // Load the value from ReturnValue
2284
  mov(eax, Operand(ebp, return_value_offset * kPointerSize));
2317
  mov(eax, return_value_operand);
2285 2318

  
2286 2319
  Label promote_scheduled_exception;
2320
  Label exception_handled;
2287 2321
  Label delete_allocated_handles;
2288 2322
  Label leave_exit_frame;
2289 2323

  
......
2303 2337
  cmp(Operand::StaticVariable(scheduled_exception_address),
2304 2338
      Immediate(isolate()->factory()->the_hole_value()));
2305 2339
  j(not_equal, &promote_scheduled_exception);
2340
  bind(&exception_handled);
2306 2341

  
2307 2342
#if ENABLE_EXTRA_CHECKS
2308 2343
  // Check if the function returned a valid JavaScript value.
......
2339 2374
  bind(&ok);
2340 2375
#endif
2341 2376

  
2342
  LeaveApiExitFrame();
2377
  bool restore_context = context_restore_operand != NULL;
2378
  if (restore_context) {
2379
    mov(esi, *context_restore_operand);
2380
  }
2381
  LeaveApiExitFrame(!restore_context);
2343 2382
  ret(stack_space * kPointerSize);
2344 2383

  
2345 2384
  bind(&promote_scheduled_exception);
2346
  TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
2385
  {
2386
    FrameScope frame(this, StackFrame::INTERNAL);
2387
    CallRuntime(Runtime::kPromoteScheduledException, 0);
2388
  }
2389
  jmp(&exception_handled);
2347 2390

  
2348 2391
  // HandleScope limit has changed. Delete allocated extensions.
2349 2392
  ExternalReference delete_extensions =
......
3003 3046
}
3004 3047

  
3005 3048

  
3049
void MacroAssembler::LookupNumberStringCache(Register object,
3050
                                             Register result,
3051
                                             Register scratch1,
3052
                                             Register scratch2,
3053
                                             Label* not_found) {
3054
  // Use of registers. Register result is used as a temporary.
3055
  Register number_string_cache = result;
3056
  Register mask = scratch1;
3057
  Register scratch = scratch2;
3058

  
3059
  // Load the number string cache.
3060
  LoadRoot(number_string_cache, Heap::kNumberStringCacheRootIndex);
3061
  // Make the hash mask from the length of the number string cache. It
3062
  // contains two elements (number and string) for each cache entry.
3063
  mov(mask, FieldOperand(number_string_cache, FixedArray::kLengthOffset));
3064
  shr(mask, kSmiTagSize + 1);  // Untag length and divide it by two.
3065
  sub(mask, Immediate(1));  // Make mask.
3066

  
3067
  // Calculate the entry in the number string cache. The hash value in the
3068
  // number string cache for smis is just the smi value, and the hash for
3069
  // doubles is the xor of the upper and lower words. See
3070
  // Heap::GetNumberStringCache.
3071
  Label smi_hash_calculated;
3072
  Label load_result_from_cache;
3073
  Label not_smi;
3074
  STATIC_ASSERT(kSmiTag == 0);
3075
  JumpIfNotSmi(object, &not_smi, Label::kNear);
3076
  mov(scratch, object);
3077
  SmiUntag(scratch);
3078
  jmp(&smi_hash_calculated, Label::kNear);
3079
  bind(&not_smi);
3080
  cmp(FieldOperand(object, HeapObject::kMapOffset),
3081
      isolate()->factory()->heap_number_map());
3082
  j(not_equal, not_found);
3083
  STATIC_ASSERT(8 == kDoubleSize);
3084
  mov(scratch, FieldOperand(object, HeapNumber::kValueOffset));
3085
  xor_(scratch, FieldOperand(object, HeapNumber::kValueOffset + 4));
3086
  // Object is heap number and hash is now in scratch. Calculate cache index.
3087
  and_(scratch, mask);
3088
  Register index = scratch;
3089
  Register probe = mask;
3090
  mov(probe,
3091
      FieldOperand(number_string_cache,
3092
                   index,
3093
                   times_twice_pointer_size,
3094
                   FixedArray::kHeaderSize));
3095
  JumpIfSmi(probe, not_found);
3096
  if (CpuFeatures::IsSupported(SSE2)) {
3097
    CpuFeatureScope fscope(this, SSE2);
3098
    movsd(xmm0, FieldOperand(object, HeapNumber::kValueOffset));
3099
    ucomisd(xmm0, FieldOperand(probe, HeapNumber::kValueOffset));
3100
  } else {
3101
    fld_d(FieldOperand(object, HeapNumber::kValueOffset));
3102
    fld_d(FieldOperand(probe, HeapNumber::kValueOffset));
3103
    FCmp();
3104
  }
3105
  j(parity_even, not_found);  // Bail out if NaN is involved.
3106
  j(not_equal, not_found);  // The cache did not contain this value.
3107
  jmp(&load_result_from_cache, Label::kNear);
3108

  
3109
  bind(&smi_hash_calculated);
3110
  // Object is smi and hash is now in scratch. Calculate cache index.
3111
  and_(scratch, mask);
3112
  // Check if the entry is the smi we are looking for.
3113
  cmp(object,
3114
      FieldOperand(number_string_cache,
3115
                   index,
3116
                   times_twice_pointer_size,
3117
                   FixedArray::kHeaderSize));
3118
  j(not_equal, not_found);
3119

  
3120
  // Get the result from the cache.
3121
  bind(&load_result_from_cache);
3122
  mov(result,
3123
      FieldOperand(number_string_cache,
3124
                   index,
3125
                   times_twice_pointer_size,
3126
                   FixedArray::kHeaderSize + kPointerSize));
3127
  IncrementCounter(isolate()->counters()->number_to_string_native(), 1);
3128
}
3129

  
3130

  
3006 3131
void MacroAssembler::JumpIfInstanceTypeIsNotSequentialAscii(
3007 3132
    Register instance_type,
3008 3133
    Register scratch,
......
3408 3533

  
3409 3534
void MacroAssembler::TestJSArrayForAllocationMemento(
3410 3535
    Register receiver_reg,
3411
    Register scratch_reg) {
3412
  Label no_memento_available;
3413

  
3536
    Register scratch_reg,
3537
    Label* no_memento_found) {
3414 3538
  ExternalReference new_space_start =
3415 3539
      ExternalReference::new_space_start(isolate());
3416 3540
  ExternalReference new_space_allocation_top =
......
3419 3543
  lea(scratch_reg, Operand(receiver_reg,
3420 3544
      JSArray::kSize + AllocationMemento::kSize - kHeapObjectTag));
3421 3545
  cmp(scratch_reg, Immediate(new_space_start));
3422
  j(less, &no_memento_available);
3546
  j(less, no_memento_found);
3423 3547
  cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top));
3424
  j(greater, &no_memento_available);
3548
  j(greater, no_memento_found);
3425 3549
  cmp(MemOperand(scratch_reg, -AllocationMemento::kSize),
3426
      Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map())));
3427
  bind(&no_memento_available);
3550
      Immediate(isolate()->factory()->allocation_memento_map()));
3428 3551
}
3429 3552

  
3430 3553

  

Also available in: Unified diff