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

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 7535004: Merge bleeding edge up to 8774 into the GC branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 4 months 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
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 223 }
224 224
225 // Return and remove the on-stack parameters. 225 // Return and remove the on-stack parameters.
226 __ ret(3 * kPointerSize); 226 __ ret(3 * kPointerSize);
227 227
228 __ bind(&slow_case); 228 __ bind(&slow_case);
229 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1); 229 __ TailCallRuntime(Runtime::kCreateArrayLiteralShallow, 3, 1);
230 } 230 }
231 231
232 232
233 // The stub returns zero for false, and a non-zero value for true. 233 // The stub expects its argument on the stack and returns its result in tos_:
234 // zero for false, and a non-zero value for true.
234 void ToBooleanStub::Generate(MacroAssembler* masm) { 235 void ToBooleanStub::Generate(MacroAssembler* masm) {
235 Label false_result, true_result, not_string; 236 Label patch;
237 const Register argument = rax;
236 const Register map = rdx; 238 const Register map = rdx;
237 239
238 __ movq(rax, Operand(rsp, 1 * kPointerSize)); 240 if (!types_.IsEmpty()) {
241 __ movq(argument, Operand(rsp, 1 * kPointerSize));
242 }
239 243
240 // undefined -> false 244 // undefined -> false
241 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 245 CheckOddball(masm, UNDEFINED, Heap::kUndefinedValueRootIndex, false, &patch);
242 __ j(equal, &false_result);
243 246
244 // Boolean -> its value 247 // Boolean -> its value
245 __ CompareRoot(rax, Heap::kFalseValueRootIndex); 248 CheckOddball(masm, BOOLEAN, Heap::kFalseValueRootIndex, false, &patch);
246 __ j(equal, &false_result); 249 CheckOddball(masm, BOOLEAN, Heap::kTrueValueRootIndex, true, &patch);
247 __ CompareRoot(rax, Heap::kTrueValueRootIndex);
248 __ j(equal, &true_result);
249
250 // Smis: 0 -> false, all other -> true
251 __ Cmp(rax, Smi::FromInt(0));
252 __ j(equal, &false_result);
253 __ JumpIfSmi(rax, &true_result);
254 250
255 // 'null' -> false. 251 // 'null' -> false.
256 __ CompareRoot(rax, Heap::kNullValueRootIndex); 252 CheckOddball(masm, NULL_TYPE, Heap::kNullValueRootIndex, false, &patch);
257 __ j(equal, &false_result, Label::kNear);
258 253
259 // Get the map of the heap object. 254 if (types_.Contains(SMI)) {
260 __ movq(map, FieldOperand(rax, HeapObject::kMapOffset)); 255 // Smis: 0 -> false, all other -> true
256 Label not_smi;
257 __ JumpIfNotSmi(argument, &not_smi, Label::kNear);
258 // argument contains the correct return value already
259 if (!tos_.is(argument)) {
260 __ movq(tos_, argument);
261 }
262 __ ret(1 * kPointerSize);
263 __ bind(&not_smi);
264 } else if (types_.NeedsMap()) {
265 // If we need a map later and have a Smi -> patch.
266 __ JumpIfSmi(argument, &patch, Label::kNear);
267 }
261 268
262 // Undetectable -> false. 269 if (types_.NeedsMap()) {
263 __ testb(FieldOperand(map, Map::kBitFieldOffset), 270 __ movq(map, FieldOperand(argument, HeapObject::kMapOffset));
264 Immediate(1 << Map::kIsUndetectable));
265 __ j(not_zero, &false_result, Label::kNear);
266 271
267 // JavaScript object -> true. 272 // Everything with a map could be undetectable, so check this now.
268 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE); 273 __ testb(FieldOperand(map, Map::kBitFieldOffset),
269 __ j(above_equal, &true_result, Label::kNear); 274 Immediate(1 << Map::kIsUndetectable));
275 // Undetectable -> false.
276 Label not_undetectable;
277 __ j(zero, &not_undetectable, Label::kNear);
278 __ Set(tos_, 0);
279 __ ret(1 * kPointerSize);
280 __ bind(&not_undetectable);
281 }
270 282
271 // String value -> false iff empty. 283 if (types_.Contains(SPEC_OBJECT)) {
272 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE); 284 // spec object -> true.
273 __ j(above_equal, &not_string, Label::kNear); 285 Label not_js_object;
274 __ cmpq(FieldOperand(rax, String::kLengthOffset), Immediate(0)); 286 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
275 __ j(zero, &false_result, Label::kNear); 287 __ j(below, &not_js_object, Label::kNear);
276 __ jmp(&true_result, Label::kNear); 288 __ Set(tos_, 1);
289 __ ret(1 * kPointerSize);
290 __ bind(&not_js_object);
291 } else if (types_.Contains(INTERNAL_OBJECT)) {
292 // We've seen a spec object for the first time -> patch.
293 __ CmpInstanceType(map, FIRST_SPEC_OBJECT_TYPE);
294 __ j(above_equal, &patch, Label::kNear);
295 }
277 296
278 __ bind(&not_string); 297 if (types_.Contains(STRING)) {
279 // HeapNumber -> false iff +0, -0, or NaN. 298 // String value -> false iff empty.
280 // These three cases set the zero flag when compared to zero using ucomisd. 299 Label not_string;
281 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex); 300 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
282 __ j(not_equal, &true_result, Label::kNear); 301 __ j(above_equal, &not_string, Label::kNear);
283 __ xorps(xmm0, xmm0); 302 __ movq(tos_, FieldOperand(argument, String::kLengthOffset));
284 __ ucomisd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); 303 __ ret(1 * kPointerSize); // the string length is OK as the return value
285 __ j(zero, &false_result, Label::kNear); 304 __ bind(&not_string);
286 // Fall through to |true_result|. 305 } else if (types_.Contains(INTERNAL_OBJECT)) {
306 // We've seen a string for the first time -> patch
307 __ CmpInstanceType(map, FIRST_NONSTRING_TYPE);
308 __ j(below, &patch, Label::kNear);
309 }
287 310
288 // Return 1/0 for true/false in tos_. 311 if (types_.Contains(HEAP_NUMBER)) {
289 __ bind(&true_result); 312 // heap number -> false iff +0, -0, or NaN.
290 __ Set(tos_, 1); 313 Label not_heap_number, false_result;
291 __ ret(1 * kPointerSize); 314 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
292 __ bind(&false_result); 315 __ j(not_equal, &not_heap_number, Label::kNear);
293 __ Set(tos_, 0); 316 __ xorps(xmm0, xmm0);
294 __ ret(1 * kPointerSize); 317 __ ucomisd(xmm0, FieldOperand(argument, HeapNumber::kValueOffset));
318 __ j(zero, &false_result, Label::kNear);
319 __ Set(tos_, 1);
320 __ ret(1 * kPointerSize);
321 __ bind(&false_result);
322 __ Set(tos_, 0);
323 __ ret(1 * kPointerSize);
324 __ bind(&not_heap_number);
325 } else if (types_.Contains(INTERNAL_OBJECT)) {
326 // We've seen a heap number for the first time -> patch
327 __ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
328 __ j(equal, &patch, Label::kNear);
329 }
330
331 if (types_.Contains(INTERNAL_OBJECT)) {
332 // internal objects -> true
333 __ Set(tos_, 1);
334 __ ret(1 * kPointerSize);
335 }
336
337 if (!types_.IsAll()) {
338 __ bind(&patch);
339 GenerateTypeTransition(masm);
340 }
295 } 341 }
296 342
297 343
298 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) { 344 void StoreBufferOverflowStub::Generate(MacroAssembler* masm) {
299 __ PushCallerSaved(save_doubles_); 345 __ PushCallerSaved(save_doubles_);
300 const int argument_count = 1; 346 const int argument_count = 1;
301 __ PrepareCallCFunction(argument_count); 347 __ PrepareCallCFunction(argument_count);
302 #ifdef _WIN64 348 #ifdef _WIN64
303 __ LoadAddress(rcx, ExternalReference::isolate_address()); 349 __ LoadAddress(rcx, ExternalReference::isolate_address());
304 #else 350 #else
305 __ LoadAddress(rdi, ExternalReference::isolate_address()); 351 __ LoadAddress(rdi, ExternalReference::isolate_address());
306 #endif 352 #endif
307 __ CallCFunction( 353 __ CallCFunction(
308 ExternalReference::store_buffer_overflow_function(masm->isolate()), 354 ExternalReference::store_buffer_overflow_function(masm->isolate()),
309 argument_count); 355 argument_count);
310 __ PopCallerSaved(save_doubles_); 356 __ PopCallerSaved(save_doubles_);
311 __ ret(0); 357 __ ret(0);
312 } 358 }
313 359
314 360
361 void ToBooleanStub::CheckOddball(MacroAssembler* masm,
362 Type type,
363 Heap::RootListIndex value,
364 bool result,
365 Label* patch) {
366 const Register argument = rax;
367 if (types_.Contains(type)) {
368 // If we see an expected oddball, return its ToBoolean value tos_.
369 Label different_value;
370 __ CompareRoot(argument, value);
371 __ j(not_equal, &different_value, Label::kNear);
372 __ Set(tos_, result ? 1 : 0);
373 __ ret(1 * kPointerSize);
374 __ bind(&different_value);
375 } else if (types_.Contains(INTERNAL_OBJECT)) {
376 // If we see an unexpected oddball and handle internal objects, we must
377 // patch because the code for internal objects doesn't handle it explictly.
378 __ CompareRoot(argument, value);
379 __ j(equal, patch);
380 }
381 }
382
383
384 void ToBooleanStub::GenerateTypeTransition(MacroAssembler* masm) {
385 __ pop(rcx); // Get return address, operand is now on top of stack.
386 __ Push(Smi::FromInt(tos_.code()));
387 __ Push(Smi::FromInt(types_.ToByte()));
388 __ push(rcx); // Push return address.
389 // Patch the caller to an appropriate specialized stub and return the
390 // operation result to the caller of the stub.
391 __ TailCallExternalReference(
392 ExternalReference(IC_Utility(IC::kToBoolean_Patch), masm->isolate()),
393 3,
394 1);
395 }
396
397
315 class FloatingPointHelper : public AllStatic { 398 class FloatingPointHelper : public AllStatic {
316 public: 399 public:
317 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles. 400 // Load the operands from rdx and rax into xmm0 and xmm1, as doubles.
318 // If the operands are not both numbers, jump to not_numbers. 401 // If the operands are not both numbers, jump to not_numbers.
319 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis. 402 // Leaves rdx and rax unchanged. SmiOperands assumes both are smis.
320 // NumberOperands assumes both are smis or heap numbers. 403 // NumberOperands assumes both are smis or heap numbers.
321 static void LoadSSE2SmiOperands(MacroAssembler* masm); 404 static void LoadSSE2SmiOperands(MacroAssembler* masm);
322 static void LoadSSE2NumberOperands(MacroAssembler* masm); 405 static void LoadSSE2NumberOperands(MacroAssembler* masm);
323 static void LoadSSE2UnknownOperands(MacroAssembler* masm, 406 static void LoadSSE2UnknownOperands(MacroAssembler* masm,
324 Label* not_numbers); 407 Label* not_numbers);
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 break; 735 break;
653 case Token::BIT_NOT: 736 case Token::BIT_NOT:
654 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION); 737 __ InvokeBuiltin(Builtins::BIT_NOT, JUMP_FUNCTION);
655 break; 738 break;
656 default: 739 default:
657 UNREACHABLE(); 740 UNREACHABLE();
658 } 741 }
659 } 742 }
660 743
661 744
662 const char* UnaryOpStub::GetName() { 745 void UnaryOpStub::PrintName(StringStream* stream) {
663 if (name_ != NULL) return name_;
664 const int kMaxNameLength = 100;
665 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
666 kMaxNameLength);
667 if (name_ == NULL) return "OOM";
668 const char* op_name = Token::Name(op_); 746 const char* op_name = Token::Name(op_);
669 const char* overwrite_name = NULL; // Make g++ happy. 747 const char* overwrite_name = NULL; // Make g++ happy.
670 switch (mode_) { 748 switch (mode_) {
671 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break; 749 case UNARY_NO_OVERWRITE: overwrite_name = "Alloc"; break;
672 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break; 750 case UNARY_OVERWRITE: overwrite_name = "Overwrite"; break;
673 } 751 }
674 752 stream->Add("UnaryOpStub_%s_%s_%s",
675 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 753 op_name,
676 "UnaryOpStub_%s_%s_%s", 754 overwrite_name,
677 op_name, 755 UnaryOpIC::GetName(operand_type_));
678 overwrite_name,
679 UnaryOpIC::GetName(operand_type_));
680 return name_;
681 } 756 }
682 757
683 758
684 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) { 759 void BinaryOpStub::GenerateTypeTransition(MacroAssembler* masm) {
685 __ pop(rcx); // Save return address. 760 __ pop(rcx); // Save return address.
686 __ push(rdx); 761 __ push(rdx);
687 __ push(rax); 762 __ push(rax);
688 // Left and right arguments are now on top. 763 // Left and right arguments are now on top.
689 // Push this stub's key. Although the operation and the type info are 764 // Push this stub's key. Although the operation and the type info are
690 // encoded into the key, the encoding is opaque, so push them too. 765 // encoded into the key, the encoding is opaque, so push them too.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
731 break; 806 break;
732 case BinaryOpIC::GENERIC: 807 case BinaryOpIC::GENERIC:
733 GenerateGeneric(masm); 808 GenerateGeneric(masm);
734 break; 809 break;
735 default: 810 default:
736 UNREACHABLE(); 811 UNREACHABLE();
737 } 812 }
738 } 813 }
739 814
740 815
741 const char* BinaryOpStub::GetName() { 816 void BinaryOpStub::PrintName(StringStream* stream) {
742 if (name_ != NULL) return name_;
743 const int kMaxNameLength = 100;
744 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
745 kMaxNameLength);
746 if (name_ == NULL) return "OOM";
747 const char* op_name = Token::Name(op_); 817 const char* op_name = Token::Name(op_);
748 const char* overwrite_name; 818 const char* overwrite_name;
749 switch (mode_) { 819 switch (mode_) {
750 case NO_OVERWRITE: overwrite_name = "Alloc"; break; 820 case NO_OVERWRITE: overwrite_name = "Alloc"; break;
751 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break; 821 case OVERWRITE_RIGHT: overwrite_name = "OverwriteRight"; break;
752 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break; 822 case OVERWRITE_LEFT: overwrite_name = "OverwriteLeft"; break;
753 default: overwrite_name = "UnknownOverwrite"; break; 823 default: overwrite_name = "UnknownOverwrite"; break;
754 } 824 }
755 825 stream->Add("BinaryOpStub_%s_%s_%s",
756 OS::SNPrintF(Vector<char>(name_, kMaxNameLength), 826 op_name,
757 "BinaryOpStub_%s_%s_%s", 827 overwrite_name,
758 op_name, 828 BinaryOpIC::GetName(operands_type_));
759 overwrite_name,
760 BinaryOpIC::GetName(operands_type_));
761 return name_;
762 } 829 }
763 830
764 831
765 void BinaryOpStub::GenerateSmiCode( 832 void BinaryOpStub::GenerateSmiCode(
766 MacroAssembler* masm, 833 MacroAssembler* masm,
767 Label* slow, 834 Label* slow,
768 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) { 835 SmiCodeGenerateHeapNumberResults allow_heapnumber_results) {
769 836
770 // Arguments to BinaryOpStub are in rdx and rax. 837 // Arguments to BinaryOpStub are in rdx and rax.
771 Register left = rdx; 838 Register left = rdx;
(...skipping 1783 matching lines...) Expand 10 before | Expand all | Expand 10 after
2555 __ bind(&setup_rest); 2622 __ bind(&setup_rest);
2556 // Argument 2: Previous index. 2623 // Argument 2: Previous index.
2557 __ movq(arg2, rbx); 2624 __ movq(arg2, rbx);
2558 2625
2559 // Argument 1: Subject string. 2626 // Argument 1: Subject string.
2560 #ifdef _WIN64 2627 #ifdef _WIN64
2561 __ movq(arg1, rdi); 2628 __ movq(arg1, rdi);
2562 #else 2629 #else
2563 // Already there in AMD64 calling convention. 2630 // Already there in AMD64 calling convention.
2564 ASSERT(arg1.is(rdi)); 2631 ASSERT(arg1.is(rdi));
2632 USE(arg1);
2565 #endif 2633 #endif
2566 2634
2567 // Locate the code entry and call it. 2635 // Locate the code entry and call it.
2568 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag)); 2636 __ addq(r11, Immediate(Code::kHeaderSize - kHeapObjectTag));
2569 __ call(r11); 2637 __ call(r11);
2570 2638
2571 __ LeaveApiExitFrame(); 2639 __ LeaveApiExitFrame();
2572 2640
2573 // Check the result. 2641 // Check the result.
2574 Label success; 2642 Label success;
(...skipping 655 matching lines...) Expand 10 before | Expand all | Expand 10 after
3230 // Slow-case: Non-function called. 3298 // Slow-case: Non-function called.
3231 __ bind(&slow); 3299 __ bind(&slow);
3232 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead 3300 // CALL_NON_FUNCTION expects the non-function callee as receiver (instead
3233 // of the original receiver from the call site). 3301 // of the original receiver from the call site).
3234 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi); 3302 __ movq(Operand(rsp, (argc_ + 1) * kPointerSize), rdi);
3235 __ Set(rax, argc_); 3303 __ Set(rax, argc_);
3236 __ Set(rbx, 0); 3304 __ Set(rbx, 0);
3237 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION); 3305 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION);
3238 Handle<Code> adaptor = 3306 Handle<Code> adaptor =
3239 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline(); 3307 Isolate::Current()->builtins()->ArgumentsAdaptorTrampoline();
3308 __ SetCallKind(rcx, CALL_AS_METHOD);
3240 __ Jump(adaptor, RelocInfo::CODE_TARGET); 3309 __ Jump(adaptor, RelocInfo::CODE_TARGET);
3241 } 3310 }
3242 3311
3243 3312
3244 bool CEntryStub::NeedsImmovableCode() { 3313 bool CEntryStub::NeedsImmovableCode() {
3245 return false; 3314 return false;
3246 } 3315 }
3247 3316
3248 3317
3249 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { 3318 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
3466 __ bind(&throw_termination_exception); 3535 __ bind(&throw_termination_exception);
3467 GenerateThrowUncatchable(masm, TERMINATION); 3536 GenerateThrowUncatchable(masm, TERMINATION);
3468 3537
3469 __ bind(&throw_normal_exception); 3538 __ bind(&throw_normal_exception);
3470 GenerateThrowTOS(masm); 3539 GenerateThrowTOS(masm);
3471 } 3540 }
3472 3541
3473 3542
3474 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { 3543 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) {
3475 Label invoke, exit; 3544 Label invoke, exit;
3476 #ifdef ENABLE_LOGGING_AND_PROFILING
3477 Label not_outermost_js, not_outermost_js_2; 3545 Label not_outermost_js, not_outermost_js_2;
3478 #endif
3479 { // NOLINT. Scope block confuses linter. 3546 { // NOLINT. Scope block confuses linter.
3480 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm); 3547 MacroAssembler::NoRootArrayScope uninitialized_root_register(masm);
3481 // Setup frame. 3548 // Setup frame.
3482 __ push(rbp); 3549 __ push(rbp);
3483 __ movq(rbp, rsp); 3550 __ movq(rbp, rsp);
3484 3551
3485 // Push the stack frame type marker twice. 3552 // Push the stack frame type marker twice.
3486 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY; 3553 int marker = is_construct ? StackFrame::ENTRY_CONSTRUCT : StackFrame::ENTRY;
3487 // Scratch register is neither callee-save, nor an argument register on any 3554 // Scratch register is neither callee-save, nor an argument register on any
3488 // platform. It's free to use at this point. 3555 // platform. It's free to use at this point.
(...skipping 24 matching lines...) Expand all
3513 3580
3514 Isolate* isolate = masm->isolate(); 3581 Isolate* isolate = masm->isolate();
3515 3582
3516 // Save copies of the top frame descriptor on the stack. 3583 // Save copies of the top frame descriptor on the stack.
3517 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address, isolate); 3584 ExternalReference c_entry_fp(Isolate::k_c_entry_fp_address, isolate);
3518 { 3585 {
3519 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 3586 Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
3520 __ push(c_entry_fp_operand); 3587 __ push(c_entry_fp_operand);
3521 } 3588 }
3522 3589
3523 #ifdef ENABLE_LOGGING_AND_PROFILING
3524 // If this is the outermost JS call, set js_entry_sp value. 3590 // If this is the outermost JS call, set js_entry_sp value.
3525 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate); 3591 ExternalReference js_entry_sp(Isolate::k_js_entry_sp_address, isolate);
3526 __ Load(rax, js_entry_sp); 3592 __ Load(rax, js_entry_sp);
3527 __ testq(rax, rax); 3593 __ testq(rax, rax);
3528 __ j(not_zero, &not_outermost_js); 3594 __ j(not_zero, &not_outermost_js);
3529 __ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); 3595 __ Push(Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
3530 __ movq(rax, rbp); 3596 __ movq(rax, rbp);
3531 __ Store(js_entry_sp, rax); 3597 __ Store(js_entry_sp, rax);
3532 Label cont; 3598 Label cont;
3533 __ jmp(&cont); 3599 __ jmp(&cont);
3534 __ bind(&not_outermost_js); 3600 __ bind(&not_outermost_js);
3535 __ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME)); 3601 __ Push(Smi::FromInt(StackFrame::INNER_JSENTRY_FRAME));
3536 __ bind(&cont); 3602 __ bind(&cont);
3537 #endif
3538 3603
3539 // Call a faked try-block that does the invoke. 3604 // Call a faked try-block that does the invoke.
3540 __ call(&invoke); 3605 __ call(&invoke);
3541 3606
3542 // Caught exception: Store result (exception) in the pending 3607 // Caught exception: Store result (exception) in the pending
3543 // exception field in the JSEnv and return a failure sentinel. 3608 // exception field in the JSEnv and return a failure sentinel.
3544 ExternalReference pending_exception(Isolate::k_pending_exception_address, 3609 ExternalReference pending_exception(Isolate::k_pending_exception_address,
3545 isolate); 3610 isolate);
3546 __ Store(pending_exception, rax); 3611 __ Store(pending_exception, rax);
3547 __ movq(rax, Failure::Exception(), RelocInfo::NONE); 3612 __ movq(rax, Failure::Exception(), RelocInfo::NONE);
(...skipping 23 matching lines...) Expand all
3571 ExternalReference entry(Builtins::kJSEntryTrampoline, isolate); 3636 ExternalReference entry(Builtins::kJSEntryTrampoline, isolate);
3572 __ Load(rax, entry); 3637 __ Load(rax, entry);
3573 } 3638 }
3574 __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize)); 3639 __ lea(kScratchRegister, FieldOperand(rax, Code::kHeaderSize));
3575 __ call(kScratchRegister); 3640 __ call(kScratchRegister);
3576 3641
3577 // Unlink this frame from the handler chain. 3642 // Unlink this frame from the handler chain.
3578 __ PopTryHandler(); 3643 __ PopTryHandler();
3579 3644
3580 __ bind(&exit); 3645 __ bind(&exit);
3581 #ifdef ENABLE_LOGGING_AND_PROFILING
3582 // Check if the current stack frame is marked as the outermost JS frame. 3646 // Check if the current stack frame is marked as the outermost JS frame.
3583 __ pop(rbx); 3647 __ pop(rbx);
3584 __ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME)); 3648 __ Cmp(rbx, Smi::FromInt(StackFrame::OUTERMOST_JSENTRY_FRAME));
3585 __ j(not_equal, &not_outermost_js_2); 3649 __ j(not_equal, &not_outermost_js_2);
3586 __ movq(kScratchRegister, js_entry_sp); 3650 __ movq(kScratchRegister, js_entry_sp);
3587 __ movq(Operand(kScratchRegister, 0), Immediate(0)); 3651 __ movq(Operand(kScratchRegister, 0), Immediate(0));
3588 __ bind(&not_outermost_js_2); 3652 __ bind(&not_outermost_js_2);
3589 #endif
3590 3653
3591 // Restore the top frame descriptor from the stack. 3654 // Restore the top frame descriptor from the stack.
3592 { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp); 3655 { Operand c_entry_fp_operand = masm->ExternalOperand(c_entry_fp);
3593 __ pop(c_entry_fp_operand); 3656 __ pop(c_entry_fp_operand);
3594 } 3657 }
3595 3658
3596 // Restore callee-saved registers (X64 conventions). 3659 // Restore callee-saved registers (X64 conventions).
3597 __ pop(rbx); 3660 __ pop(rbx);
3598 #ifdef _WIN64 3661 #ifdef _WIN64
3599 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI. 3662 // Callee save on in Win64 ABI, arguments/volatile in AMD64 ABI.
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
3793 | RegisterField::encode(false) // lhs_ and rhs_ are not used 3856 | RegisterField::encode(false) // lhs_ and rhs_ are not used
3794 | StrictField::encode(strict_) 3857 | StrictField::encode(strict_)
3795 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false) 3858 | NeverNanNanField::encode(cc_ == equal ? never_nan_nan_ : false)
3796 | IncludeNumberCompareField::encode(include_number_compare_) 3859 | IncludeNumberCompareField::encode(include_number_compare_)
3797 | IncludeSmiCompareField::encode(include_smi_compare_); 3860 | IncludeSmiCompareField::encode(include_smi_compare_);
3798 } 3861 }
3799 3862
3800 3863
3801 // Unfortunately you have to run without snapshots to see most of these 3864 // Unfortunately you have to run without snapshots to see most of these
3802 // names in the profile since most compare stubs end up in the snapshot. 3865 // names in the profile since most compare stubs end up in the snapshot.
3803 const char* CompareStub::GetName() { 3866 void CompareStub::PrintName(StringStream* stream) {
3804 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg)); 3867 ASSERT(lhs_.is(no_reg) && rhs_.is(no_reg));
3805
3806 if (name_ != NULL) return name_;
3807 const int kMaxNameLength = 100;
3808 name_ = Isolate::Current()->bootstrapper()->AllocateAutoDeletedArray(
3809 kMaxNameLength);
3810 if (name_ == NULL) return "OOM";
3811
3812 const char* cc_name; 3868 const char* cc_name;
3813 switch (cc_) { 3869 switch (cc_) {
3814 case less: cc_name = "LT"; break; 3870 case less: cc_name = "LT"; break;
3815 case greater: cc_name = "GT"; break; 3871 case greater: cc_name = "GT"; break;
3816 case less_equal: cc_name = "LE"; break; 3872 case less_equal: cc_name = "LE"; break;
3817 case greater_equal: cc_name = "GE"; break; 3873 case greater_equal: cc_name = "GE"; break;
3818 case equal: cc_name = "EQ"; break; 3874 case equal: cc_name = "EQ"; break;
3819 case not_equal: cc_name = "NE"; break; 3875 case not_equal: cc_name = "NE"; break;
3820 default: cc_name = "UnknownCondition"; break; 3876 default: cc_name = "UnknownCondition"; break;
3821 } 3877 }
3822 3878 bool is_equality = cc_ == equal || cc_ == not_equal;
3823 const char* strict_name = ""; 3879 stream->Add("CompareStub_%s", cc_name);
3824 if (strict_ && (cc_ == equal || cc_ == not_equal)) { 3880 if (strict_ && is_equality) stream->Add("_STRICT");
3825 strict_name = "_STRICT"; 3881 if (never_nan_nan_ && is_equality) stream->Add("_NO_NAN");
3826 } 3882 if (!include_number_compare_) stream->Add("_NO_NUMBER");
3827 3883 if (!include_smi_compare_) stream->Add("_NO_SMI");
3828 const char* never_nan_nan_name = "";
3829 if (never_nan_nan_ && (cc_ == equal || cc_ == not_equal)) {
3830 never_nan_nan_name = "_NO_NAN";
3831 }
3832
3833 const char* include_number_compare_name = "";
3834 if (!include_number_compare_) {
3835 include_number_compare_name = "_NO_NUMBER";
3836 }
3837
3838 const char* include_smi_compare_name = "";
3839 if (!include_smi_compare_) {
3840 include_smi_compare_name = "_NO_SMI";
3841 }
3842
3843 OS::SNPrintF(Vector<char>(name_, kMaxNameLength),
3844 "CompareStub_%s%s%s%s",
3845 cc_name,
3846 strict_name,
3847 never_nan_nan_name,
3848 include_number_compare_name,
3849 include_smi_compare_name);
3850 return name_;
3851 } 3884 }
3852 3885
3853 3886
3854 // ------------------------------------------------------------------------- 3887 // -------------------------------------------------------------------------
3855 // StringCharCodeAtGenerator 3888 // StringCharCodeAtGenerator
3856 3889
3857 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { 3890 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
3858 Label flat_string; 3891 Label flat_string;
3859 Label ascii_string; 3892 Label ascii_string;
3860 Label got_char_code; 3893 Label got_char_code;
(...skipping 1647 matching lines...) Expand 10 before | Expand all | Expand 10 after
5508 // TODO(gc): Add call to EnsureNotWhite here. 5541 // TODO(gc): Add call to EnsureNotWhite here.
5509 // Fall through when we need to inform the incremental marker. 5542 // Fall through when we need to inform the incremental marker.
5510 } 5543 }
5511 5544
5512 5545
5513 #undef __ 5546 #undef __
5514 5547
5515 } } // namespace v8::internal 5548 } } // namespace v8::internal
5516 5549
5517 #endif // V8_TARGET_ARCH_X64 5550 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/code-stubs-x64.h ('k') | src/x64/codegen-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698