Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(173)

Side by Side Diff: src/ia32/lithium-codegen-ia32.cc

Issue 110573004: Merge bleeding_edge 17696:18016. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 #ifdef _MSC_VER 123 #ifdef _MSC_VER
124 void LCodeGen::MakeSureStackPagesMapped(int offset) { 124 void LCodeGen::MakeSureStackPagesMapped(int offset) {
125 const int kPageSize = 4 * KB; 125 const int kPageSize = 4 * KB;
126 for (offset -= kPageSize; offset > 0; offset -= kPageSize) { 126 for (offset -= kPageSize; offset > 0; offset -= kPageSize) {
127 __ mov(Operand(esp, offset), eax); 127 __ mov(Operand(esp, offset), eax);
128 } 128 }
129 } 129 }
130 #endif 130 #endif
131 131
132 132
133 void LCodeGen::SaveCallerDoubles() {
134 ASSERT(info()->saves_caller_doubles());
135 ASSERT(NeedsEagerFrame());
136 Comment(";;; Save clobbered callee double registers");
137 CpuFeatureScope scope(masm(), SSE2);
138 int count = 0;
139 BitVector* doubles = chunk()->allocated_double_registers();
140 BitVector::Iterator save_iterator(doubles);
141 while (!save_iterator.Done()) {
142 __ movsd(MemOperand(esp, count * kDoubleSize),
143 XMMRegister::FromAllocationIndex(save_iterator.Current()));
144 save_iterator.Advance();
145 count++;
146 }
147 }
148
149
150 void LCodeGen::RestoreCallerDoubles() {
151 ASSERT(info()->saves_caller_doubles());
152 ASSERT(NeedsEagerFrame());
153 Comment(";;; Restore clobbered callee double registers");
154 CpuFeatureScope scope(masm(), SSE2);
155 BitVector* doubles = chunk()->allocated_double_registers();
156 BitVector::Iterator save_iterator(doubles);
157 int count = 0;
158 while (!save_iterator.Done()) {
159 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
160 MemOperand(esp, count * kDoubleSize));
161 save_iterator.Advance();
162 count++;
163 }
164 }
165
166
133 bool LCodeGen::GeneratePrologue() { 167 bool LCodeGen::GeneratePrologue() {
134 ASSERT(is_generating()); 168 ASSERT(is_generating());
135 169
136 if (info()->IsOptimizing()) { 170 if (info()->IsOptimizing()) {
137 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 171 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
138 172
139 #ifdef DEBUG 173 #ifdef DEBUG
140 if (strlen(FLAG_stop_at) > 0 && 174 if (strlen(FLAG_stop_at) > 0 &&
141 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 175 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
142 __ int3(); 176 __ int3();
(...skipping 10 matching lines...) Expand all
153 __ j(zero, &ok, Label::kNear); 187 __ j(zero, &ok, Label::kNear);
154 // +1 for return address. 188 // +1 for return address.
155 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize; 189 int receiver_offset = (scope()->num_parameters() + 1) * kPointerSize;
156 __ mov(Operand(esp, receiver_offset), 190 __ mov(Operand(esp, receiver_offset),
157 Immediate(isolate()->factory()->undefined_value())); 191 Immediate(isolate()->factory()->undefined_value()));
158 __ bind(&ok); 192 __ bind(&ok);
159 } 193 }
160 194
161 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { 195 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
162 // Move state of dynamic frame alignment into edx. 196 // Move state of dynamic frame alignment into edx.
163 __ mov(edx, Immediate(kNoAlignmentPadding)); 197 __ Set(edx, Immediate(kNoAlignmentPadding));
164 198
165 Label do_not_pad, align_loop; 199 Label do_not_pad, align_loop;
166 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize); 200 STATIC_ASSERT(kDoubleSize == 2 * kPointerSize);
167 // Align esp + 4 to a multiple of 2 * kPointerSize. 201 // Align esp + 4 to a multiple of 2 * kPointerSize.
168 __ test(esp, Immediate(kPointerSize)); 202 __ test(esp, Immediate(kPointerSize));
169 __ j(not_zero, &do_not_pad, Label::kNear); 203 __ j(not_zero, &do_not_pad, Label::kNear);
170 __ push(Immediate(0)); 204 __ push(Immediate(0));
171 __ mov(ebx, esp); 205 __ mov(ebx, esp);
172 __ mov(edx, Immediate(kAlignmentPaddingPushed)); 206 __ mov(edx, Immediate(kAlignmentPaddingPushed));
173 // Copy arguments, receiver, and return address. 207 // Copy arguments, receiver, and return address.
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset; 271 int offset = JavaScriptFrameConstants::kDynamicAlignmentStateOffset;
238 if (dynamic_frame_alignment_) { 272 if (dynamic_frame_alignment_) {
239 __ mov(Operand(ebp, offset), edx); 273 __ mov(Operand(ebp, offset), edx);
240 } else { 274 } else {
241 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding)); 275 __ mov(Operand(ebp, offset), Immediate(kNoAlignmentPadding));
242 } 276 }
243 } 277 }
244 } 278 }
245 279
246 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { 280 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
247 Comment(";;; Save clobbered callee double registers"); 281 SaveCallerDoubles();
248 CpuFeatureScope scope(masm(), SSE2);
249 int count = 0;
250 BitVector* doubles = chunk()->allocated_double_registers();
251 BitVector::Iterator save_iterator(doubles);
252 while (!save_iterator.Done()) {
253 __ movsd(MemOperand(esp, count * kDoubleSize),
254 XMMRegister::FromAllocationIndex(save_iterator.Current()));
255 save_iterator.Advance();
256 count++;
257 }
258 } 282 }
259 } 283 }
260 284
261 // Possibly allocate a local context. 285 // Possibly allocate a local context.
262 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; 286 int heap_slots = info_->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
263 if (heap_slots > 0) { 287 if (heap_slots > 0) {
264 Comment(";;; Allocate local context"); 288 Comment(";;; Allocate local context");
265 // Argument to NewContext is the function, which is still in edi. 289 // Argument to NewContext is the function, which is still in edi.
266 __ push(edi); 290 __ push(edi);
267 if (heap_slots <= FastNewContextStub::kMaximumSlots) { 291 if (heap_slots <= FastNewContextStub::kMaximumSlots) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 333
310 334
311 void LCodeGen::GenerateOsrPrologue() { 335 void LCodeGen::GenerateOsrPrologue() {
312 // Generate the OSR entry prologue at the first unknown OSR value, or if there 336 // Generate the OSR entry prologue at the first unknown OSR value, or if there
313 // are none, at the OSR entrypoint instruction. 337 // are none, at the OSR entrypoint instruction.
314 if (osr_pc_offset_ >= 0) return; 338 if (osr_pc_offset_ >= 0) return;
315 339
316 osr_pc_offset_ = masm()->pc_offset(); 340 osr_pc_offset_ = masm()->pc_offset();
317 341
318 // Move state of dynamic frame alignment into edx. 342 // Move state of dynamic frame alignment into edx.
319 __ mov(edx, Immediate(kNoAlignmentPadding)); 343 __ Set(edx, Immediate(kNoAlignmentPadding));
320 344
321 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) { 345 if (support_aligned_spilled_doubles_ && dynamic_frame_alignment_) {
322 Label do_not_pad, align_loop; 346 Label do_not_pad, align_loop;
323 // Align ebp + 4 to a multiple of 2 * kPointerSize. 347 // Align ebp + 4 to a multiple of 2 * kPointerSize.
324 __ test(ebp, Immediate(kPointerSize)); 348 __ test(ebp, Immediate(kPointerSize));
325 __ j(zero, &do_not_pad, Label::kNear); 349 __ j(zero, &do_not_pad, Label::kNear);
326 __ push(Immediate(0)); 350 __ push(Immediate(0));
327 __ mov(ebx, esp); 351 __ mov(ebx, esp);
328 __ mov(edx, Immediate(kAlignmentPaddingPushed)); 352 __ mov(edx, Immediate(kAlignmentPaddingPushed));
329 353
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 __ bind(&jump_table_[i].label); 416 __ bind(&jump_table_[i].label);
393 Address entry = jump_table_[i].address; 417 Address entry = jump_table_[i].address;
394 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; 418 Deoptimizer::BailoutType type = jump_table_[i].bailout_type;
395 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); 419 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type);
396 if (id == Deoptimizer::kNotDeoptimizationEntry) { 420 if (id == Deoptimizer::kNotDeoptimizationEntry) {
397 Comment(";;; jump table entry %d.", i); 421 Comment(";;; jump table entry %d.", i);
398 } else { 422 } else {
399 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); 423 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id);
400 } 424 }
401 if (jump_table_[i].needs_frame) { 425 if (jump_table_[i].needs_frame) {
426 ASSERT(!info()->saves_caller_doubles());
402 __ push(Immediate(ExternalReference::ForDeoptEntry(entry))); 427 __ push(Immediate(ExternalReference::ForDeoptEntry(entry)));
403 if (needs_frame.is_bound()) { 428 if (needs_frame.is_bound()) {
404 __ jmp(&needs_frame); 429 __ jmp(&needs_frame);
405 } else { 430 } else {
406 __ bind(&needs_frame); 431 __ bind(&needs_frame);
407 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset)); 432 __ push(MemOperand(ebp, StandardFrameConstants::kContextOffset));
408 // This variant of deopt can only be used with stubs. Since we don't 433 // This variant of deopt can only be used with stubs. Since we don't
409 // have a function pointer to install in the stack frame that we're 434 // have a function pointer to install in the stack frame that we're
410 // building, install a special marker there instead. 435 // building, install a special marker there instead.
411 ASSERT(info()->IsStub()); 436 ASSERT(info()->IsStub());
412 __ push(Immediate(Smi::FromInt(StackFrame::STUB))); 437 __ push(Immediate(Smi::FromInt(StackFrame::STUB)));
413 // Push a PC inside the function so that the deopt code can find where 438 // Push a PC inside the function so that the deopt code can find where
414 // the deopt comes from. It doesn't have to be the precise return 439 // the deopt comes from. It doesn't have to be the precise return
415 // address of a "calling" LAZY deopt, it only has to be somewhere 440 // address of a "calling" LAZY deopt, it only has to be somewhere
416 // inside the code body. 441 // inside the code body.
417 Label push_approx_pc; 442 Label push_approx_pc;
418 __ call(&push_approx_pc); 443 __ call(&push_approx_pc);
419 __ bind(&push_approx_pc); 444 __ bind(&push_approx_pc);
420 // Push the continuation which was stashed were the ebp should 445 // Push the continuation which was stashed were the ebp should
421 // be. Replace it with the saved ebp. 446 // be. Replace it with the saved ebp.
422 __ push(MemOperand(esp, 3 * kPointerSize)); 447 __ push(MemOperand(esp, 3 * kPointerSize));
423 __ mov(MemOperand(esp, 4 * kPointerSize), ebp); 448 __ mov(MemOperand(esp, 4 * kPointerSize), ebp);
424 __ lea(ebp, MemOperand(esp, 4 * kPointerSize)); 449 __ lea(ebp, MemOperand(esp, 4 * kPointerSize));
425 __ ret(0); // Call the continuation without clobbering registers. 450 __ ret(0); // Call the continuation without clobbering registers.
426 } 451 }
427 } else { 452 } else {
453 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
454 RestoreCallerDoubles();
455 }
428 __ call(entry, RelocInfo::RUNTIME_ENTRY); 456 __ call(entry, RelocInfo::RUNTIME_ENTRY);
429 } 457 }
430 } 458 }
431 return !is_aborted(); 459 return !is_aborted();
432 } 460 }
433 461
434 462
435 bool LCodeGen::GenerateDeferredCode() { 463 bool LCodeGen::GenerateDeferredCode() {
436 ASSERT(is_generating()); 464 ASSERT(is_generating());
437 if (deferred_.length() > 0) { 465 if (deferred_.length() > 0) {
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 bool LCodeGen::IsInteger32(LConstantOperand* op) const { 802 bool LCodeGen::IsInteger32(LConstantOperand* op) const {
775 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); 803 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32();
776 } 804 }
777 805
778 806
779 bool LCodeGen::IsSmi(LConstantOperand* op) const { 807 bool LCodeGen::IsSmi(LConstantOperand* op) const {
780 return chunk_->LookupLiteralRepresentation(op).IsSmi(); 808 return chunk_->LookupLiteralRepresentation(op).IsSmi();
781 } 809 }
782 810
783 811
812 static int ArgumentsOffsetWithoutFrame(int index) {
813 ASSERT(index < 0);
814 return -(index + 1) * kPointerSize + kPCOnStackSize;
815 }
816
817
784 Operand LCodeGen::ToOperand(LOperand* op) const { 818 Operand LCodeGen::ToOperand(LOperand* op) const {
785 if (op->IsRegister()) return Operand(ToRegister(op)); 819 if (op->IsRegister()) return Operand(ToRegister(op));
786 if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op)); 820 if (op->IsDoubleRegister()) return Operand(ToDoubleRegister(op));
787 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 821 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
788 return Operand(ebp, StackSlotOffset(op->index())); 822 if (NeedsEagerFrame()) {
823 return Operand(ebp, StackSlotOffset(op->index()));
824 } else {
825 // Retrieve parameter without eager stack-frame relative to the
826 // stack-pointer.
827 return Operand(esp, ArgumentsOffsetWithoutFrame(op->index()));
828 }
789 } 829 }
790 830
791 831
792 Operand LCodeGen::HighOperand(LOperand* op) { 832 Operand LCodeGen::HighOperand(LOperand* op) {
793 ASSERT(op->IsDoubleStackSlot()); 833 ASSERT(op->IsDoubleStackSlot());
794 return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize); 834 if (NeedsEagerFrame()) {
835 return Operand(ebp, StackSlotOffset(op->index()) + kPointerSize);
836 } else {
837 // Retrieve parameter without eager stack-frame relative to the
838 // stack-pointer.
839 return Operand(
840 esp, ArgumentsOffsetWithoutFrame(op->index()) + kPointerSize);
841 }
795 } 842 }
796 843
797 844
798 void LCodeGen::WriteTranslation(LEnvironment* environment, 845 void LCodeGen::WriteTranslation(LEnvironment* environment,
799 Translation* translation) { 846 Translation* translation) {
800 if (environment == NULL) return; 847 if (environment == NULL) return;
801 848
802 // The translation includes one command per value in the environment. 849 // The translation includes one command per value in the environment.
803 int translation_size = environment->translation_size(); 850 int translation_size = environment->translation_size();
804 // The output frame height does not include the parameters. 851 // The output frame height does not include the parameters.
(...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after
1373 __ neg(left_reg); 1420 __ neg(left_reg);
1374 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1421 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1375 DeoptimizeIf(zero, instr->environment()); 1422 DeoptimizeIf(zero, instr->environment());
1376 } 1423 }
1377 __ jmp(&done, Label::kNear); 1424 __ jmp(&done, Label::kNear);
1378 } 1425 }
1379 1426
1380 __ bind(&left_is_not_negative); 1427 __ bind(&left_is_not_negative);
1381 __ and_(left_reg, divisor - 1); 1428 __ and_(left_reg, divisor - 1);
1382 __ bind(&done); 1429 __ bind(&done);
1383
1384 } else if (hmod->fixed_right_arg().has_value) {
1385 Register left_reg = ToRegister(instr->left());
1386 ASSERT(left_reg.is(ToRegister(instr->result())));
1387 Register right_reg = ToRegister(instr->right());
1388
1389 int32_t divisor = hmod->fixed_right_arg().value;
1390 ASSERT(IsPowerOf2(divisor));
1391
1392 // Check if our assumption of a fixed right operand still holds.
1393 __ cmp(right_reg, Immediate(divisor));
1394 DeoptimizeIf(not_equal, instr->environment());
1395
1396 Label left_is_not_negative, done;
1397 if (left->CanBeNegative()) {
1398 __ test(left_reg, Operand(left_reg));
1399 __ j(not_sign, &left_is_not_negative, Label::kNear);
1400 __ neg(left_reg);
1401 __ and_(left_reg, divisor - 1);
1402 __ neg(left_reg);
1403 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1404 DeoptimizeIf(zero, instr->environment());
1405 }
1406 __ jmp(&done, Label::kNear);
1407 }
1408
1409 __ bind(&left_is_not_negative);
1410 __ and_(left_reg, divisor - 1);
1411 __ bind(&done);
1412
1413 } else { 1430 } else {
1414 Register left_reg = ToRegister(instr->left()); 1431 Register left_reg = ToRegister(instr->left());
1415 ASSERT(left_reg.is(eax)); 1432 ASSERT(left_reg.is(eax));
1416 Register right_reg = ToRegister(instr->right()); 1433 Register right_reg = ToRegister(instr->right());
1417 ASSERT(!right_reg.is(eax)); 1434 ASSERT(!right_reg.is(eax));
1418 ASSERT(!right_reg.is(edx)); 1435 ASSERT(!right_reg.is(edx));
1419 Register result_reg = ToRegister(instr->result()); 1436 Register result_reg = ToRegister(instr->result());
1420 ASSERT(result_reg.is(edx)); 1437 ASSERT(result_reg.is(edx));
1421 1438
1422 Label done; 1439 Label done;
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
2104 __ movzx_w(result, operand); 2121 __ movzx_w(result, operand);
2105 } 2122 }
2106 } 2123 }
2107 2124
2108 2125
2109 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) { 2126 void LCodeGen::DoSeqStringSetChar(LSeqStringSetChar* instr) {
2110 String::Encoding encoding = instr->hydrogen()->encoding(); 2127 String::Encoding encoding = instr->hydrogen()->encoding();
2111 Register string = ToRegister(instr->string()); 2128 Register string = ToRegister(instr->string());
2112 2129
2113 if (FLAG_debug_code) { 2130 if (FLAG_debug_code) {
2114 __ push(string); 2131 Register value = ToRegister(instr->value());
2115 __ mov(string, FieldOperand(string, HeapObject::kMapOffset)); 2132 Register index = ToRegister(instr->index());
2116 __ movzx_b(string, FieldOperand(string, Map::kInstanceTypeOffset));
2117
2118 __ and_(string, Immediate(kStringRepresentationMask | kStringEncodingMask));
2119 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag; 2133 static const uint32_t one_byte_seq_type = kSeqStringTag | kOneByteStringTag;
2120 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag; 2134 static const uint32_t two_byte_seq_type = kSeqStringTag | kTwoByteStringTag;
2121 __ cmp(string, Immediate(encoding == String::ONE_BYTE_ENCODING 2135 int encoding_mask =
2122 ? one_byte_seq_type : two_byte_seq_type)); 2136 instr->hydrogen()->encoding() == String::ONE_BYTE_ENCODING
2123 __ Check(equal, kUnexpectedStringType); 2137 ? one_byte_seq_type : two_byte_seq_type;
2124 __ pop(string); 2138 __ EmitSeqStringSetCharCheck(string, index, value, encoding_mask);
2125 } 2139 }
2126 2140
2127 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding); 2141 Operand operand = BuildSeqStringOperand(string, instr->index(), encoding);
2128 if (instr->value()->IsConstantOperand()) { 2142 if (instr->value()->IsConstantOperand()) {
2129 int value = ToRepresentation(LConstantOperand::cast(instr->value()), 2143 int value = ToRepresentation(LConstantOperand::cast(instr->value()),
2130 Representation::Integer32()); 2144 Representation::Integer32());
2131 ASSERT_LE(0, value); 2145 ASSERT_LE(0, value);
2132 if (encoding == String::ONE_BYTE_ENCODING) { 2146 if (encoding == String::ONE_BYTE_ENCODING) {
2133 ASSERT_LE(value, String::kMaxOneByteCharCode); 2147 ASSERT_LE(value, String::kMaxOneByteCharCode);
2134 __ mov_b(operand, static_cast<int8_t>(value)); 2148 __ mov_b(operand, static_cast<int8_t>(value));
(...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after
3136 if (FLAG_trace && info()->IsOptimizing()) { 3150 if (FLAG_trace && info()->IsOptimizing()) {
3137 // Preserve the return value on the stack and rely on the runtime call 3151 // Preserve the return value on the stack and rely on the runtime call
3138 // to return the value in the same register. We're leaving the code 3152 // to return the value in the same register. We're leaving the code
3139 // managed by the register allocator and tearing down the frame, it's 3153 // managed by the register allocator and tearing down the frame, it's
3140 // safe to write to the context register. 3154 // safe to write to the context register.
3141 __ push(eax); 3155 __ push(eax);
3142 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); 3156 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
3143 __ CallRuntime(Runtime::kTraceExit, 1); 3157 __ CallRuntime(Runtime::kTraceExit, 1);
3144 } 3158 }
3145 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) { 3159 if (info()->saves_caller_doubles() && CpuFeatures::IsSupported(SSE2)) {
3146 ASSERT(NeedsEagerFrame()); 3160 RestoreCallerDoubles();
3147 CpuFeatureScope scope(masm(), SSE2);
3148 BitVector* doubles = chunk()->allocated_double_registers();
3149 BitVector::Iterator save_iterator(doubles);
3150 int count = 0;
3151 while (!save_iterator.Done()) {
3152 __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
3153 MemOperand(esp, count * kDoubleSize));
3154 save_iterator.Advance();
3155 count++;
3156 }
3157 } 3161 }
3158 if (dynamic_frame_alignment_) { 3162 if (dynamic_frame_alignment_) {
3159 // Fetch the state of the dynamic frame alignment. 3163 // Fetch the state of the dynamic frame alignment.
3160 __ mov(edx, Operand(ebp, 3164 __ mov(edx, Operand(ebp,
3161 JavaScriptFrameConstants::kDynamicAlignmentStateOffset)); 3165 JavaScriptFrameConstants::kDynamicAlignmentStateOffset));
3162 } 3166 }
3163 int no_frame_start = -1; 3167 int no_frame_start = -1;
3164 if (NeedsEagerFrame()) { 3168 if (NeedsEagerFrame()) {
3165 __ mov(esp, ebp); 3169 __ mov(esp, ebp);
3166 __ pop(ebp); 3170 __ pop(ebp);
(...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after
4174 MathPowStub stub(MathPowStub::INTEGER); 4178 MathPowStub stub(MathPowStub::INTEGER);
4175 __ CallStub(&stub); 4179 __ CallStub(&stub);
4176 } else { 4180 } else {
4177 ASSERT(exponent_type.IsDouble()); 4181 ASSERT(exponent_type.IsDouble());
4178 MathPowStub stub(MathPowStub::DOUBLE); 4182 MathPowStub stub(MathPowStub::DOUBLE);
4179 __ CallStub(&stub); 4183 __ CallStub(&stub);
4180 } 4184 }
4181 } 4185 }
4182 4186
4183 4187
4184 void LCodeGen::DoRandom(LRandom* instr) {
4185 CpuFeatureScope scope(masm(), SSE2);
4186
4187 // Assert that the register size is indeed the size of each seed.
4188 static const int kSeedSize = sizeof(uint32_t);
4189 STATIC_ASSERT(kPointerSize == kSeedSize);
4190
4191 // Load native context
4192 Register global_object = ToRegister(instr->global_object());
4193 Register native_context = global_object;
4194 __ mov(native_context, FieldOperand(
4195 global_object, GlobalObject::kNativeContextOffset));
4196
4197 // Load state (FixedArray of the native context's random seeds)
4198 static const int kRandomSeedOffset =
4199 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
4200 Register state = native_context;
4201 __ mov(state, FieldOperand(native_context, kRandomSeedOffset));
4202
4203 // Load state[0].
4204 Register state0 = ToRegister(instr->scratch());
4205 __ mov(state0, FieldOperand(state, ByteArray::kHeaderSize));
4206 // Load state[1].
4207 Register state1 = ToRegister(instr->scratch2());
4208 __ mov(state1, FieldOperand(state, ByteArray::kHeaderSize + kSeedSize));
4209
4210 // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
4211 Register scratch3 = ToRegister(instr->scratch3());
4212 __ movzx_w(scratch3, state0);
4213 __ imul(scratch3, scratch3, 18273);
4214 __ shr(state0, 16);
4215 __ add(state0, scratch3);
4216 // Save state[0].
4217 __ mov(FieldOperand(state, ByteArray::kHeaderSize), state0);
4218
4219 // state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16)
4220 __ movzx_w(scratch3, state1);
4221 __ imul(scratch3, scratch3, 36969);
4222 __ shr(state1, 16);
4223 __ add(state1, scratch3);
4224 // Save state[1].
4225 __ mov(FieldOperand(state, ByteArray::kHeaderSize + kSeedSize), state1);
4226
4227 // Random bit pattern = (state[0] << 14) + (state[1] & 0x3FFFF)
4228 Register random = state0;
4229 __ shl(random, 14);
4230 __ and_(state1, Immediate(0x3FFFF));
4231 __ add(random, state1);
4232
4233 // Convert 32 random bits in random to 0.(32 random bits) in a double
4234 // by computing:
4235 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)).
4236 XMMRegister result = ToDoubleRegister(instr->result());
4237 XMMRegister scratch4 = double_scratch0();
4238 __ mov(scratch3, Immediate(0x49800000)); // 1.0 x 2^20 as single.
4239 __ movd(scratch4, scratch3);
4240 __ movd(result, random);
4241 __ cvtss2sd(scratch4, scratch4);
4242 __ xorps(result, scratch4);
4243 __ subsd(result, scratch4);
4244 }
4245
4246
4247 void LCodeGen::DoMathLog(LMathLog* instr) { 4188 void LCodeGen::DoMathLog(LMathLog* instr) {
4248 CpuFeatureScope scope(masm(), SSE2); 4189 CpuFeatureScope scope(masm(), SSE2);
4249 ASSERT(instr->value()->Equals(instr->result())); 4190 ASSERT(instr->value()->Equals(instr->result()));
4250 XMMRegister input_reg = ToDoubleRegister(instr->value()); 4191 XMMRegister input_reg = ToDoubleRegister(instr->value());
4251 XMMRegister xmm_scratch = double_scratch0(); 4192 XMMRegister xmm_scratch = double_scratch0();
4252 Label positive, done, zero; 4193 Label positive, done, zero;
4253 __ xorps(xmm_scratch, xmm_scratch); 4194 __ xorps(xmm_scratch, xmm_scratch);
4254 __ ucomisd(input_reg, xmm_scratch); 4195 __ ucomisd(input_reg, xmm_scratch);
4255 __ j(above, &positive, Label::kNear); 4196 __ j(above, &positive, Label::kNear);
4256 __ j(equal, &zero, Label::kNear); 4197 __ j(equal, &zero, Label::kNear);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
4369 } 4310 }
4370 4311
4371 4312
4372 void LCodeGen::DoCallFunction(LCallFunction* instr) { 4313 void LCodeGen::DoCallFunction(LCallFunction* instr) {
4373 ASSERT(ToRegister(instr->context()).is(esi)); 4314 ASSERT(ToRegister(instr->context()).is(esi));
4374 ASSERT(ToRegister(instr->function()).is(edi)); 4315 ASSERT(ToRegister(instr->function()).is(edi));
4375 ASSERT(ToRegister(instr->result()).is(eax)); 4316 ASSERT(ToRegister(instr->result()).is(eax));
4376 4317
4377 int arity = instr->arity(); 4318 int arity = instr->arity();
4378 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); 4319 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS);
4379 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 4320 if (instr->hydrogen()->IsTailCall()) {
4321 if (NeedsEagerFrame()) __ leave();
4322 __ jmp(stub.GetCode(isolate()), RelocInfo::CODE_TARGET);
4323 } else {
4324 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
4325 }
4380 } 4326 }
4381 4327
4382 4328
4383 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { 4329 void LCodeGen::DoCallGlobal(LCallGlobal* instr) {
4384 ASSERT(ToRegister(instr->context()).is(esi)); 4330 ASSERT(ToRegister(instr->context()).is(esi));
4385 ASSERT(ToRegister(instr->result()).is(eax)); 4331 ASSERT(ToRegister(instr->result()).is(eax));
4386 4332
4387 int arity = instr->arity(); 4333 int arity = instr->arity();
4388 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; 4334 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT;
4389 Handle<Code> ic = 4335 Handle<Code> ic =
(...skipping 1635 matching lines...) Expand 10 before | Expand all | Expand 10 after
6025 } 5971 }
6026 } 5972 }
6027 5973
6028 5974
6029 void LCodeGen::DoDeferredAllocate(LAllocate* instr) { 5975 void LCodeGen::DoDeferredAllocate(LAllocate* instr) {
6030 Register result = ToRegister(instr->result()); 5976 Register result = ToRegister(instr->result());
6031 5977
6032 // TODO(3095996): Get rid of this. For now, we need to make the 5978 // TODO(3095996): Get rid of this. For now, we need to make the
6033 // result register contain a valid pointer because it is already 5979 // result register contain a valid pointer because it is already
6034 // contained in the register pointer map. 5980 // contained in the register pointer map.
6035 __ mov(result, Immediate(Smi::FromInt(0))); 5981 __ Set(result, Immediate(Smi::FromInt(0)));
6036 5982
6037 PushSafepointRegistersScope scope(this); 5983 PushSafepointRegistersScope scope(this);
6038 if (instr->size()->IsRegister()) { 5984 if (instr->size()->IsRegister()) {
6039 Register size = ToRegister(instr->size()); 5985 Register size = ToRegister(instr->size());
6040 ASSERT(!size.is(result)); 5986 ASSERT(!size.is(result));
6041 __ SmiTag(ToRegister(instr->size())); 5987 __ SmiTag(ToRegister(instr->size()));
6042 __ push(size); 5988 __ push(size);
6043 } else { 5989 } else {
6044 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); 5990 int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
6045 __ push(Immediate(Smi::FromInt(size))); 5991 __ push(Immediate(Smi::FromInt(size)));
6046 } 5992 }
6047 5993
5994 int flags = AllocateDoubleAlignFlag::encode(
5995 instr->hydrogen()->MustAllocateDoubleAligned());
6048 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { 5996 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) {
6049 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); 5997 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation());
6050 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); 5998 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
6051 CallRuntimeFromDeferred( 5999 flags = AllocateTargetSpace::update(flags, OLD_POINTER_SPACE);
6052 Runtime::kAllocateInOldPointerSpace, 1, instr, instr->context());
6053 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { 6000 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) {
6054 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); 6001 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation());
6055 CallRuntimeFromDeferred( 6002 flags = AllocateTargetSpace::update(flags, OLD_DATA_SPACE);
6056 Runtime::kAllocateInOldDataSpace, 1, instr, instr->context());
6057 } else { 6003 } else {
6058 CallRuntimeFromDeferred( 6004 flags = AllocateTargetSpace::update(flags, NEW_SPACE);
6059 Runtime::kAllocateInNewSpace, 1, instr, instr->context());
6060 } 6005 }
6006 __ push(Immediate(Smi::FromInt(flags)));
6007
6008 CallRuntimeFromDeferred(
6009 Runtime::kAllocateInTargetSpace, 2, instr, instr->context());
6061 __ StoreToSafepointRegisterSlot(result, eax); 6010 __ StoreToSafepointRegisterSlot(result, eax);
6062 } 6011 }
6063 6012
6064 6013
6065 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { 6014 void LCodeGen::DoToFastProperties(LToFastProperties* instr) {
6066 ASSERT(ToRegister(instr->value()).is(eax)); 6015 ASSERT(ToRegister(instr->value()).is(eax));
6067 __ push(eax); 6016 __ push(eax);
6068 CallRuntime(Runtime::kToFastProperties, 1, instr); 6017 CallRuntime(Runtime::kToFastProperties, 1, instr);
6069 } 6018 }
6070 6019
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
6144 void LCodeGen::DoTypeof(LTypeof* instr) { 6093 void LCodeGen::DoTypeof(LTypeof* instr) {
6145 ASSERT(ToRegister(instr->context()).is(esi)); 6094 ASSERT(ToRegister(instr->context()).is(esi));
6146 LOperand* input = instr->value(); 6095 LOperand* input = instr->value();
6147 EmitPushTaggedOperand(input); 6096 EmitPushTaggedOperand(input);
6148 CallRuntime(Runtime::kTypeof, 1, instr); 6097 CallRuntime(Runtime::kTypeof, 1, instr);
6149 } 6098 }
6150 6099
6151 6100
6152 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { 6101 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
6153 Register input = ToRegister(instr->value()); 6102 Register input = ToRegister(instr->value());
6154 6103 Condition final_branch_condition = EmitTypeofIs(instr, input);
6155 Condition final_branch_condition =
6156 EmitTypeofIs(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
6157 input, instr->type_literal());
6158 if (final_branch_condition != no_condition) { 6104 if (final_branch_condition != no_condition) {
6159 EmitBranch(instr, final_branch_condition); 6105 EmitBranch(instr, final_branch_condition);
6160 } 6106 }
6161 } 6107 }
6162 6108
6163 6109
6164 Condition LCodeGen::EmitTypeofIs(Label* true_label, 6110 Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
6165 Label* false_label, 6111 Label* true_label = instr->TrueLabel(chunk_);
6166 Register input, 6112 Label* false_label = instr->FalseLabel(chunk_);
6167 Handle<String> type_name) { 6113 Handle<String> type_name = instr->type_literal();
6114 int left_block = instr->TrueDestination(chunk_);
6115 int right_block = instr->FalseDestination(chunk_);
6116 int next_block = GetNextEmittedBlock();
6117
6118 Label::Distance true_distance = left_block == next_block ? Label::kNear
6119 : Label::kFar;
6120 Label::Distance false_distance = right_block == next_block ? Label::kNear
6121 : Label::kFar;
6168 Condition final_branch_condition = no_condition; 6122 Condition final_branch_condition = no_condition;
6169 if (type_name->Equals(heap()->number_string())) { 6123 if (type_name->Equals(heap()->number_string())) {
6170 __ JumpIfSmi(input, true_label); 6124 __ JumpIfSmi(input, true_label, true_distance);
6171 __ cmp(FieldOperand(input, HeapObject::kMapOffset), 6125 __ cmp(FieldOperand(input, HeapObject::kMapOffset),
6172 factory()->heap_number_map()); 6126 factory()->heap_number_map());
6173 final_branch_condition = equal; 6127 final_branch_condition = equal;
6174 6128
6175 } else if (type_name->Equals(heap()->string_string())) { 6129 } else if (type_name->Equals(heap()->string_string())) {
6176 __ JumpIfSmi(input, false_label); 6130 __ JumpIfSmi(input, false_label, false_distance);
6177 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); 6131 __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
6178 __ j(above_equal, false_label); 6132 __ j(above_equal, false_label, false_distance);
6179 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 6133 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
6180 1 << Map::kIsUndetectable); 6134 1 << Map::kIsUndetectable);
6181 final_branch_condition = zero; 6135 final_branch_condition = zero;
6182 6136
6183 } else if (type_name->Equals(heap()->symbol_string())) { 6137 } else if (type_name->Equals(heap()->symbol_string())) {
6184 __ JumpIfSmi(input, false_label); 6138 __ JumpIfSmi(input, false_label, false_distance);
6185 __ CmpObjectType(input, SYMBOL_TYPE, input); 6139 __ CmpObjectType(input, SYMBOL_TYPE, input);
6186 final_branch_condition = equal; 6140 final_branch_condition = equal;
6187 6141
6188 } else if (type_name->Equals(heap()->boolean_string())) { 6142 } else if (type_name->Equals(heap()->boolean_string())) {
6189 __ cmp(input, factory()->true_value()); 6143 __ cmp(input, factory()->true_value());
6190 __ j(equal, true_label); 6144 __ j(equal, true_label, true_distance);
6191 __ cmp(input, factory()->false_value()); 6145 __ cmp(input, factory()->false_value());
6192 final_branch_condition = equal; 6146 final_branch_condition = equal;
6193 6147
6194 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) { 6148 } else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
6195 __ cmp(input, factory()->null_value()); 6149 __ cmp(input, factory()->null_value());
6196 final_branch_condition = equal; 6150 final_branch_condition = equal;
6197 6151
6198 } else if (type_name->Equals(heap()->undefined_string())) { 6152 } else if (type_name->Equals(heap()->undefined_string())) {
6199 __ cmp(input, factory()->undefined_value()); 6153 __ cmp(input, factory()->undefined_value());
6200 __ j(equal, true_label); 6154 __ j(equal, true_label, true_distance);
6201 __ JumpIfSmi(input, false_label); 6155 __ JumpIfSmi(input, false_label, false_distance);
6202 // Check for undetectable objects => true. 6156 // Check for undetectable objects => true.
6203 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); 6157 __ mov(input, FieldOperand(input, HeapObject::kMapOffset));
6204 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 6158 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
6205 1 << Map::kIsUndetectable); 6159 1 << Map::kIsUndetectable);
6206 final_branch_condition = not_zero; 6160 final_branch_condition = not_zero;
6207 6161
6208 } else if (type_name->Equals(heap()->function_string())) { 6162 } else if (type_name->Equals(heap()->function_string())) {
6209 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); 6163 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
6210 __ JumpIfSmi(input, false_label); 6164 __ JumpIfSmi(input, false_label, false_distance);
6211 __ CmpObjectType(input, JS_FUNCTION_TYPE, input); 6165 __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
6212 __ j(equal, true_label); 6166 __ j(equal, true_label, true_distance);
6213 __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); 6167 __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
6214 final_branch_condition = equal; 6168 final_branch_condition = equal;
6215 6169
6216 } else if (type_name->Equals(heap()->object_string())) { 6170 } else if (type_name->Equals(heap()->object_string())) {
6217 __ JumpIfSmi(input, false_label); 6171 __ JumpIfSmi(input, false_label, false_distance);
6218 if (!FLAG_harmony_typeof) { 6172 if (!FLAG_harmony_typeof) {
6219 __ cmp(input, factory()->null_value()); 6173 __ cmp(input, factory()->null_value());
6220 __ j(equal, true_label); 6174 __ j(equal, true_label, true_distance);
6221 } 6175 }
6222 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input); 6176 __ CmpObjectType(input, FIRST_NONCALLABLE_SPEC_OBJECT_TYPE, input);
6223 __ j(below, false_label); 6177 __ j(below, false_label, false_distance);
6224 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE); 6178 __ CmpInstanceType(input, LAST_NONCALLABLE_SPEC_OBJECT_TYPE);
6225 __ j(above, false_label); 6179 __ j(above, false_label, false_distance);
6226 // Check for undetectable objects => false. 6180 // Check for undetectable objects => false.
6227 __ test_b(FieldOperand(input, Map::kBitFieldOffset), 6181 __ test_b(FieldOperand(input, Map::kBitFieldOffset),
6228 1 << Map::kIsUndetectable); 6182 1 << Map::kIsUndetectable);
6229 final_branch_condition = zero; 6183 final_branch_condition = zero;
6230 6184
6231 } else { 6185 } else {
6232 __ jmp(false_label); 6186 __ jmp(false_label, false_distance);
6233 } 6187 }
6234 return final_branch_condition; 6188 return final_branch_condition;
6235 } 6189 }
6236 6190
6237 6191
6238 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { 6192 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) {
6239 Register temp = ToRegister(instr->temp()); 6193 Register temp = ToRegister(instr->temp());
6240 6194
6241 EmitIsConstructCall(temp); 6195 EmitIsConstructCall(temp);
6242 EmitBranch(instr, equal); 6196 EmitBranch(instr, equal);
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
6477 FixedArray::kHeaderSize - kPointerSize)); 6431 FixedArray::kHeaderSize - kPointerSize));
6478 __ bind(&done); 6432 __ bind(&done);
6479 } 6433 }
6480 6434
6481 6435
6482 #undef __ 6436 #undef __
6483 6437
6484 } } // namespace v8::internal 6438 } } // namespace v8::internal
6485 6439
6486 #endif // V8_TARGET_ARCH_IA32 6440 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698