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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 6529032: Merge 6168:6800 from bleeding_edge to experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 10 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/macro-assembler-x64.cc ('k') | src/x64/virtual-frame-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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 ASSERT(kNotStringTag != 0); 300 ASSERT(kNotStringTag != 0);
301 __ testl(scratch, Immediate(kNotStringTag)); 301 __ testl(scratch, Immediate(kNotStringTag));
302 __ j(not_zero, non_string_object); 302 __ j(not_zero, non_string_object);
303 } 303 }
304 304
305 305
306 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 306 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
307 Register receiver, 307 Register receiver,
308 Register scratch1, 308 Register scratch1,
309 Register scratch2, 309 Register scratch2,
310 Label* miss) { 310 Label* miss,
311 bool support_wrappers) {
311 Label check_wrapper; 312 Label check_wrapper;
312 313
313 // Check if the object is a string leaving the instance type in the 314 // Check if the object is a string leaving the instance type in the
314 // scratch register. 315 // scratch register.
315 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); 316 GenerateStringCheck(masm, receiver, scratch1, miss,
317 support_wrappers ? &check_wrapper : miss);
316 318
317 // Load length directly from the string. 319 // Load length directly from the string.
318 __ movq(rax, FieldOperand(receiver, String::kLengthOffset)); 320 __ movq(rax, FieldOperand(receiver, String::kLengthOffset));
319 __ ret(0); 321 __ ret(0);
320 322
321 // Check if the object is a JSValue wrapper. 323 if (support_wrappers) {
322 __ bind(&check_wrapper); 324 // Check if the object is a JSValue wrapper.
323 __ cmpl(scratch1, Immediate(JS_VALUE_TYPE)); 325 __ bind(&check_wrapper);
324 __ j(not_equal, miss); 326 __ cmpl(scratch1, Immediate(JS_VALUE_TYPE));
327 __ j(not_equal, miss);
325 328
326 // Check if the wrapped value is a string and load the length 329 // Check if the wrapped value is a string and load the length
327 // directly if it is. 330 // directly if it is.
328 __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); 331 __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
329 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); 332 GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
330 __ movq(rax, FieldOperand(scratch2, String::kLengthOffset)); 333 __ movq(rax, FieldOperand(scratch2, String::kLengthOffset));
331 __ ret(0); 334 __ ret(0);
335 }
332 } 336 }
333 337
334 338
335 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 339 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
336 Register receiver, 340 Register receiver,
337 Register result, 341 Register result,
338 Register scratch, 342 Register scratch,
339 Label* miss_label) { 343 Label* miss_label) {
340 __ TryGetFunctionPrototype(receiver, result, miss_label); 344 __ TryGetFunctionPrototype(receiver, result, miss_label);
341 if (!result.is(rax)) __ movq(rax, result); 345 if (!result.is(rax)) __ movq(rax, result);
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal 434 // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal
431 // frame. 435 // frame.
432 // ----------------------------------- 436 // -----------------------------------
433 __ movq(scratch, Operand(rsp, 0)); 437 __ movq(scratch, Operand(rsp, 0));
434 __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch); 438 __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch);
435 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); 439 __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments));
436 } 440 }
437 441
438 442
439 // Generates call to API function. 443 // Generates call to API function.
440 static bool GenerateFastApiCall(MacroAssembler* masm, 444 static MaybeObject* GenerateFastApiCall(MacroAssembler* masm,
441 const CallOptimization& optimization, 445 const CallOptimization& optimization,
442 int argc, 446 int argc) {
443 Failure** failure) {
444 // ----------- S t a t e ------------- 447 // ----------- S t a t e -------------
445 // -- rsp[0] : return address 448 // -- rsp[0] : return address
446 // -- rsp[8] : object passing the type check 449 // -- rsp[8] : object passing the type check
447 // (last fast api call extra argument, 450 // (last fast api call extra argument,
448 // set by CheckPrototypes) 451 // set by CheckPrototypes)
449 // -- rsp[16] : api function 452 // -- rsp[16] : api function
450 // (first fast api call extra argument) 453 // (first fast api call extra argument)
451 // -- rsp[24] : api call data 454 // -- rsp[24] : api call data
452 // -- rsp[32] : last argument 455 // -- rsp[32] : last argument
453 // -- ... 456 // -- ...
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
497 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. 500 __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_.
498 // v8::Arguments::is_construct_call_. 501 // v8::Arguments::is_construct_call_.
499 __ Set(StackSpaceOperand(3), 0); 502 __ Set(StackSpaceOperand(3), 0);
500 503
501 // v8::InvocationCallback's argument. 504 // v8::InvocationCallback's argument.
502 __ lea(arguments_arg, StackSpaceOperand(0)); 505 __ lea(arguments_arg, StackSpaceOperand(0));
503 // Emitting a stub call may try to allocate (if the code is not 506 // Emitting a stub call may try to allocate (if the code is not
504 // already generated). Do not allow the assembler to perform a 507 // already generated). Do not allow the assembler to perform a
505 // garbage collection but instead return the allocation failure 508 // garbage collection but instead return the allocation failure
506 // object. 509 // object.
507 MaybeObject* result = 510 return masm->TryCallApiFunctionAndReturn(&fun,
508 masm->TryCallApiFunctionAndReturn(&fun, argc + kFastApiCallArguments + 1); 511 argc + kFastApiCallArguments + 1);
509 if (result->IsFailure()) {
510 *failure = Failure::cast(result);
511 return false;
512 }
513 return true;
514 } 512 }
515 513
516 514
517 class CallInterceptorCompiler BASE_EMBEDDED { 515 class CallInterceptorCompiler BASE_EMBEDDED {
518 public: 516 public:
519 CallInterceptorCompiler(StubCompiler* stub_compiler, 517 CallInterceptorCompiler(StubCompiler* stub_compiler,
520 const ParameterCount& arguments, 518 const ParameterCount& arguments,
521 Register name) 519 Register name)
522 : stub_compiler_(stub_compiler), 520 : stub_compiler_(stub_compiler),
523 arguments_(arguments), 521 arguments_(arguments),
524 name_(name) {} 522 name_(name) {}
525 523
526 bool Compile(MacroAssembler* masm, 524 MaybeObject* Compile(MacroAssembler* masm,
527 JSObject* object, 525 JSObject* object,
528 JSObject* holder, 526 JSObject* holder,
529 String* name, 527 String* name,
530 LookupResult* lookup, 528 LookupResult* lookup,
531 Register receiver, 529 Register receiver,
532 Register scratch1, 530 Register scratch1,
533 Register scratch2, 531 Register scratch2,
534 Register scratch3, 532 Register scratch3,
535 Label* miss, 533 Label* miss) {
536 Failure** failure) {
537 ASSERT(holder->HasNamedInterceptor()); 534 ASSERT(holder->HasNamedInterceptor());
538 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 535 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
539 536
540 // Check that the receiver isn't a smi. 537 // Check that the receiver isn't a smi.
541 __ JumpIfSmi(receiver, miss); 538 __ JumpIfSmi(receiver, miss);
542 539
543 CallOptimization optimization(lookup); 540 CallOptimization optimization(lookup);
544 541
545 if (optimization.is_constant_call()) { 542 if (optimization.is_constant_call()) {
546 return CompileCacheable(masm, 543 return CompileCacheable(masm,
547 object, 544 object,
548 receiver, 545 receiver,
549 scratch1, 546 scratch1,
550 scratch2, 547 scratch2,
551 scratch3, 548 scratch3,
552 holder, 549 holder,
553 lookup, 550 lookup,
554 name, 551 name,
555 optimization, 552 optimization,
556 miss, 553 miss);
557 failure);
558 } else { 554 } else {
559 CompileRegular(masm, 555 CompileRegular(masm,
560 object, 556 object,
561 receiver, 557 receiver,
562 scratch1, 558 scratch1,
563 scratch2, 559 scratch2,
564 scratch3, 560 scratch3,
565 name, 561 name,
566 holder, 562 holder,
567 miss); 563 miss);
568 return true; 564 return Heap::undefined_value(); // Success.
569 } 565 }
570 } 566 }
571 567
572 private: 568 private:
573 bool CompileCacheable(MacroAssembler* masm, 569 MaybeObject* CompileCacheable(MacroAssembler* masm,
574 JSObject* object, 570 JSObject* object,
575 Register receiver, 571 Register receiver,
576 Register scratch1, 572 Register scratch1,
577 Register scratch2, 573 Register scratch2,
578 Register scratch3, 574 Register scratch3,
579 JSObject* interceptor_holder, 575 JSObject* interceptor_holder,
580 LookupResult* lookup, 576 LookupResult* lookup,
581 String* name, 577 String* name,
582 const CallOptimization& optimization, 578 const CallOptimization& optimization,
583 Label* miss_label, 579 Label* miss_label) {
584 Failure** failure) {
585 ASSERT(optimization.is_constant_call()); 580 ASSERT(optimization.is_constant_call());
586 ASSERT(!lookup->holder()->IsGlobalObject()); 581 ASSERT(!lookup->holder()->IsGlobalObject());
587 582
588 int depth1 = kInvalidProtoDepth; 583 int depth1 = kInvalidProtoDepth;
589 int depth2 = kInvalidProtoDepth; 584 int depth2 = kInvalidProtoDepth;
590 bool can_do_fast_api_call = false; 585 bool can_do_fast_api_call = false;
591 if (optimization.is_simple_api_call() && 586 if (optimization.is_simple_api_call() &&
592 !lookup->holder()->IsGlobalObject()) { 587 !lookup->holder()->IsGlobalObject()) {
593 depth1 = 588 depth1 =
594 optimization.GetPrototypeDepthOfExpectedType(object, 589 optimization.GetPrototypeDepthOfExpectedType(object,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
636 } else { 631 } else {
637 // CheckPrototypes has a side effect of fetching a 'holder' 632 // CheckPrototypes has a side effect of fetching a 'holder'
638 // for API (object which is instanceof for the signature). It's 633 // for API (object which is instanceof for the signature). It's
639 // safe to omit it here, as if present, it should be fetched 634 // safe to omit it here, as if present, it should be fetched
640 // by the previous CheckPrototypes. 635 // by the previous CheckPrototypes.
641 ASSERT(depth2 == kInvalidProtoDepth); 636 ASSERT(depth2 == kInvalidProtoDepth);
642 } 637 }
643 638
644 // Invoke function. 639 // Invoke function.
645 if (can_do_fast_api_call) { 640 if (can_do_fast_api_call) {
646 bool success = GenerateFastApiCall(masm, 641 MaybeObject* result = GenerateFastApiCall(masm,
647 optimization, 642 optimization,
648 arguments_.immediate(), 643 arguments_.immediate());
649 failure); 644 if (result->IsFailure()) return result;
650 if (!success) {
651 return false;
652 }
653 } else { 645 } else {
654 __ InvokeFunction(optimization.constant_function(), arguments_, 646 __ InvokeFunction(optimization.constant_function(), arguments_,
655 JUMP_FUNCTION); 647 JUMP_FUNCTION);
656 } 648 }
657 649
658 // Deferred code for fast API call case---clean preallocated space. 650 // Deferred code for fast API call case---clean preallocated space.
659 if (can_do_fast_api_call) { 651 if (can_do_fast_api_call) {
660 __ bind(&miss_cleanup); 652 __ bind(&miss_cleanup);
661 FreeSpaceForFastApiCall(masm, scratch1); 653 FreeSpaceForFastApiCall(masm, scratch1);
662 __ jmp(miss_label); 654 __ jmp(miss_label);
663 } 655 }
664 656
665 // Invoke a regular function. 657 // Invoke a regular function.
666 __ bind(&regular_invoke); 658 __ bind(&regular_invoke);
667 if (can_do_fast_api_call) { 659 if (can_do_fast_api_call) {
668 FreeSpaceForFastApiCall(masm, scratch1); 660 FreeSpaceForFastApiCall(masm, scratch1);
669 } 661 }
670 662
671 return true; 663 return Heap::undefined_value(); // Success.
672 } 664 }
673 665
674 void CompileRegular(MacroAssembler* masm, 666 void CompileRegular(MacroAssembler* masm,
675 JSObject* object, 667 JSObject* object,
676 Register receiver, 668 Register receiver,
677 Register scratch1, 669 Register scratch1,
678 Register scratch2, 670 Register scratch2,
679 Register scratch3, 671 Register scratch3,
680 String* name, 672 String* name,
681 JSObject* interceptor_holder, 673 JSObject* interceptor_holder,
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1014 Register reg = 1006 Register reg =
1015 CheckPrototypes(object, receiver, holder, 1007 CheckPrototypes(object, receiver, holder,
1016 scratch1, scratch2, scratch3, name, miss); 1008 scratch1, scratch2, scratch3, name, miss);
1017 1009
1018 // Get the value from the properties. 1010 // Get the value from the properties.
1019 GenerateFastPropertyLoad(masm(), rax, reg, holder, index); 1011 GenerateFastPropertyLoad(masm(), rax, reg, holder, index);
1020 __ ret(0); 1012 __ ret(0);
1021 } 1013 }
1022 1014
1023 1015
1024 bool StubCompiler::GenerateLoadCallback(JSObject* object, 1016 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
1025 JSObject* holder, 1017 JSObject* holder,
1026 Register receiver, 1018 Register receiver,
1027 Register name_reg, 1019 Register name_reg,
1028 Register scratch1, 1020 Register scratch1,
1029 Register scratch2, 1021 Register scratch2,
1030 Register scratch3, 1022 Register scratch3,
1031 AccessorInfo* callback, 1023 AccessorInfo* callback,
1032 String* name, 1024 String* name,
1033 Label* miss, 1025 Label* miss) {
1034 Failure** failure) {
1035 // Check that the receiver isn't a smi. 1026 // Check that the receiver isn't a smi.
1036 __ JumpIfSmi(receiver, miss); 1027 __ JumpIfSmi(receiver, miss);
1037 1028
1038 // Check that the maps haven't changed. 1029 // Check that the maps haven't changed.
1039 Register reg = 1030 Register reg =
1040 CheckPrototypes(object, receiver, holder, scratch1, 1031 CheckPrototypes(object, receiver, holder, scratch1,
1041 scratch2, scratch3, name, miss); 1032 scratch2, scratch3, name, miss);
1042 1033
1043 Handle<AccessorInfo> callback_handle(callback); 1034 Handle<AccessorInfo> callback_handle(callback);
1044 1035
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1088 __ movq(StackSpaceOperand(0), rax); 1079 __ movq(StackSpaceOperand(0), rax);
1089 1080
1090 // The context register (rsi) has been saved in PrepareCallApiFunction and 1081 // The context register (rsi) has been saved in PrepareCallApiFunction and
1091 // could be used to pass arguments. 1082 // could be used to pass arguments.
1092 __ lea(accessor_info_arg, StackSpaceOperand(0)); 1083 __ lea(accessor_info_arg, StackSpaceOperand(0));
1093 1084
1094 // Emitting a stub call may try to allocate (if the code is not 1085 // Emitting a stub call may try to allocate (if the code is not
1095 // already generated). Do not allow the assembler to perform a 1086 // already generated). Do not allow the assembler to perform a
1096 // garbage collection but instead return the allocation failure 1087 // garbage collection but instead return the allocation failure
1097 // object. 1088 // object.
1098 MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); 1089 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
1099 if (result->IsFailure()) {
1100 *failure = Failure::cast(result);
1101 return false;
1102 }
1103 return true;
1104 } 1090 }
1105 1091
1106 1092
1107 void StubCompiler::GenerateLoadConstant(JSObject* object, 1093 void StubCompiler::GenerateLoadConstant(JSObject* object,
1108 JSObject* holder, 1094 JSObject* holder,
1109 Register receiver, 1095 Register receiver,
1110 Register scratch1, 1096 Register scratch1,
1111 Register scratch2, 1097 Register scratch2,
1112 Register scratch3, 1098 Register scratch3,
1113 Object* value, 1099 Object* value,
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
1320 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); 1306 __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax);
1321 __ j(not_equal, miss); 1307 __ j(not_equal, miss);
1322 } else { 1308 } else {
1323 __ Cmp(rdi, Handle<JSFunction>(function)); 1309 __ Cmp(rdi, Handle<JSFunction>(function));
1324 __ j(not_equal, miss); 1310 __ j(not_equal, miss);
1325 } 1311 }
1326 } 1312 }
1327 1313
1328 1314
1329 MaybeObject* CallStubCompiler::GenerateMissBranch() { 1315 MaybeObject* CallStubCompiler::GenerateMissBranch() {
1330 MaybeObject* maybe_obj = 1316 MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(),
1331 StubCache::ComputeCallMiss(arguments().immediate(), kind_); 1317 kind_);
1332 Object* obj; 1318 Object* obj;
1333 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1319 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1334 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); 1320 __ Jump(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
1335 return obj; 1321 return obj;
1336 } 1322 }
1337 1323
1338 1324
1339 MaybeObject* CallStubCompiler::CompileCallField(JSObject* object, 1325 MaybeObject* CallStubCompiler::CompileCallField(JSObject* object,
1340 JSObject* holder, 1326 JSObject* holder,
1341 int index, 1327 int index,
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after
1653 // -- ... 1639 // -- ...
1654 // -- rsp[(argc + 1) * 8] : receiver 1640 // -- rsp[(argc + 1) * 8] : receiver
1655 // ----------------------------------- 1641 // -----------------------------------
1656 1642
1657 // If object is not a string, bail out to regular call. 1643 // If object is not a string, bail out to regular call.
1658 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); 1644 if (!object->IsString() || cell != NULL) return Heap::undefined_value();
1659 1645
1660 const int argc = arguments().immediate(); 1646 const int argc = arguments().immediate();
1661 1647
1662 Label miss; 1648 Label miss;
1649 Label name_miss;
1663 Label index_out_of_range; 1650 Label index_out_of_range;
1651 Label* index_out_of_range_label = &index_out_of_range;
1664 1652
1665 GenerateNameCheck(name, &miss); 1653 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
1654 index_out_of_range_label = &miss;
1655 }
1656
1657 GenerateNameCheck(name, &name_miss);
1666 1658
1667 // Check that the maps starting from the prototype haven't changed. 1659 // Check that the maps starting from the prototype haven't changed.
1668 GenerateDirectLoadGlobalFunctionPrototype(masm(), 1660 GenerateDirectLoadGlobalFunctionPrototype(masm(),
1669 Context::STRING_FUNCTION_INDEX, 1661 Context::STRING_FUNCTION_INDEX,
1670 rax, 1662 rax,
1671 &miss); 1663 &miss);
1672 ASSERT(object != holder); 1664 ASSERT(object != holder);
1673 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, 1665 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
1674 rbx, rdx, rdi, name, &miss); 1666 rbx, rdx, rdi, name, &miss);
1675 1667
1676 Register receiver = rbx; 1668 Register receiver = rbx;
1677 Register index = rdi; 1669 Register index = rdi;
1678 Register scratch = rdx; 1670 Register scratch = rdx;
1679 Register result = rax; 1671 Register result = rax;
1680 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 1672 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
1681 if (argc > 0) { 1673 if (argc > 0) {
1682 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 1674 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
1683 } else { 1675 } else {
1684 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 1676 __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1685 } 1677 }
1686 1678
1687 StringCharCodeAtGenerator char_code_at_generator(receiver, 1679 StringCharCodeAtGenerator char_code_at_generator(receiver,
1688 index, 1680 index,
1689 scratch, 1681 scratch,
1690 result, 1682 result,
1691 &miss, // When not a string. 1683 &miss, // When not a string.
1692 &miss, // When not a number. 1684 &miss, // When not a number.
1693 &index_out_of_range, 1685 index_out_of_range_label,
1694 STRING_INDEX_IS_NUMBER); 1686 STRING_INDEX_IS_NUMBER);
1695 char_code_at_generator.GenerateFast(masm()); 1687 char_code_at_generator.GenerateFast(masm());
1696 __ ret((argc + 1) * kPointerSize); 1688 __ ret((argc + 1) * kPointerSize);
1697 1689
1698 StubRuntimeCallHelper call_helper; 1690 StubRuntimeCallHelper call_helper;
1699 char_code_at_generator.GenerateSlow(masm(), call_helper); 1691 char_code_at_generator.GenerateSlow(masm(), call_helper);
1700 1692
1701 __ bind(&index_out_of_range); 1693 if (index_out_of_range.is_linked()) {
1702 __ LoadRoot(rax, Heap::kNanValueRootIndex); 1694 __ bind(&index_out_of_range);
1703 __ ret((argc + 1) * kPointerSize); 1695 __ LoadRoot(rax, Heap::kNanValueRootIndex);
1696 __ ret((argc + 1) * kPointerSize);
1697 }
1704 1698
1705 __ bind(&miss); 1699 __ bind(&miss);
1700 // Restore function name in rcx.
1701 __ Move(rcx, Handle<String>(name));
1702 __ bind(&name_miss);
1706 Object* obj; 1703 Object* obj;
1707 { MaybeObject* maybe_obj = GenerateMissBranch(); 1704 { MaybeObject* maybe_obj = GenerateMissBranch();
1708 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1705 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1709 } 1706 }
1710 1707
1711 // Return the generated code. 1708 // Return the generated code.
1712 return GetCode(function); 1709 return GetCode(function);
1713 } 1710 }
1714 1711
1715 1712
(...skipping 10 matching lines...) Expand all
1726 // -- ... 1723 // -- ...
1727 // -- rsp[(argc + 1) * 8] : receiver 1724 // -- rsp[(argc + 1) * 8] : receiver
1728 // ----------------------------------- 1725 // -----------------------------------
1729 1726
1730 // If object is not a string, bail out to regular call. 1727 // If object is not a string, bail out to regular call.
1731 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); 1728 if (!object->IsString() || cell != NULL) return Heap::undefined_value();
1732 1729
1733 const int argc = arguments().immediate(); 1730 const int argc = arguments().immediate();
1734 1731
1735 Label miss; 1732 Label miss;
1733 Label name_miss;
1736 Label index_out_of_range; 1734 Label index_out_of_range;
1735 Label* index_out_of_range_label = &index_out_of_range;
1737 1736
1738 GenerateNameCheck(name, &miss); 1737 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
1738 index_out_of_range_label = &miss;
1739 }
1740
1741 GenerateNameCheck(name, &name_miss);
1739 1742
1740 // Check that the maps starting from the prototype haven't changed. 1743 // Check that the maps starting from the prototype haven't changed.
1741 GenerateDirectLoadGlobalFunctionPrototype(masm(), 1744 GenerateDirectLoadGlobalFunctionPrototype(masm(),
1742 Context::STRING_FUNCTION_INDEX, 1745 Context::STRING_FUNCTION_INDEX,
1743 rax, 1746 rax,
1744 &miss); 1747 &miss);
1745 ASSERT(object != holder); 1748 ASSERT(object != holder);
1746 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder, 1749 CheckPrototypes(JSObject::cast(object->GetPrototype()), rax, holder,
1747 rbx, rdx, rdi, name, &miss); 1750 rbx, rdx, rdi, name, &miss);
1748 1751
1749 Register receiver = rax; 1752 Register receiver = rax;
1750 Register index = rdi; 1753 Register index = rdi;
1751 Register scratch1 = rbx; 1754 Register scratch1 = rbx;
1752 Register scratch2 = rdx; 1755 Register scratch2 = rdx;
1753 Register result = rax; 1756 Register result = rax;
1754 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 1757 __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize));
1755 if (argc > 0) { 1758 if (argc > 0) {
1756 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 1759 __ movq(index, Operand(rsp, (argc - 0) * kPointerSize));
1757 } else { 1760 } else {
1758 __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 1761 __ LoadRoot(index, Heap::kUndefinedValueRootIndex);
1759 } 1762 }
1760 1763
1761 StringCharAtGenerator char_at_generator(receiver, 1764 StringCharAtGenerator char_at_generator(receiver,
1762 index, 1765 index,
1763 scratch1, 1766 scratch1,
1764 scratch2, 1767 scratch2,
1765 result, 1768 result,
1766 &miss, // When not a string. 1769 &miss, // When not a string.
1767 &miss, // When not a number. 1770 &miss, // When not a number.
1768 &index_out_of_range, 1771 index_out_of_range_label,
1769 STRING_INDEX_IS_NUMBER); 1772 STRING_INDEX_IS_NUMBER);
1770 char_at_generator.GenerateFast(masm()); 1773 char_at_generator.GenerateFast(masm());
1771 __ ret((argc + 1) * kPointerSize); 1774 __ ret((argc + 1) * kPointerSize);
1772 1775
1773 StubRuntimeCallHelper call_helper; 1776 StubRuntimeCallHelper call_helper;
1774 char_at_generator.GenerateSlow(masm(), call_helper); 1777 char_at_generator.GenerateSlow(masm(), call_helper);
1775 1778
1776 __ bind(&index_out_of_range); 1779 if (index_out_of_range.is_linked()) {
1777 __ LoadRoot(rax, Heap::kEmptyStringRootIndex); 1780 __ bind(&index_out_of_range);
1778 __ ret((argc + 1) * kPointerSize); 1781 __ LoadRoot(rax, Heap::kEmptyStringRootIndex);
1782 __ ret((argc + 1) * kPointerSize);
1783 }
1779 1784
1780 __ bind(&miss); 1785 __ bind(&miss);
1786 // Restore function name in rcx.
1787 __ Move(rcx, Handle<String>(name));
1788 __ bind(&name_miss);
1781 Object* obj; 1789 Object* obj;
1782 { MaybeObject* maybe_obj = GenerateMissBranch(); 1790 { MaybeObject* maybe_obj = GenerateMissBranch();
1783 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1791 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1784 } 1792 }
1785 1793
1786 // Return the generated code. 1794 // Return the generated code.
1787 return GetCode(function); 1795 return GetCode(function);
1788 } 1796 }
1789 1797
1790 1798
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
2106 rbx, rdx, rdi, name, &miss); 2114 rbx, rdx, rdi, name, &miss);
2107 } 2115 }
2108 break; 2116 break;
2109 } 2117 }
2110 2118
2111 default: 2119 default:
2112 UNREACHABLE(); 2120 UNREACHABLE();
2113 } 2121 }
2114 2122
2115 if (depth != kInvalidProtoDepth) { 2123 if (depth != kInvalidProtoDepth) {
2116 Failure* failure;
2117 // Move the return address on top of the stack. 2124 // Move the return address on top of the stack.
2118 __ movq(rax, Operand(rsp, 3 * kPointerSize)); 2125 __ movq(rax, Operand(rsp, 3 * kPointerSize));
2119 __ movq(Operand(rsp, 0 * kPointerSize), rax); 2126 __ movq(Operand(rsp, 0 * kPointerSize), rax);
2120 2127
2121 // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains 2128 // rsp[2 * kPointerSize] is uninitialized, rsp[3 * kPointerSize] contains
2122 // duplicate of return address and will be overwritten. 2129 // duplicate of return address and will be overwritten.
2123 bool success = GenerateFastApiCall(masm(), optimization, argc, &failure); 2130 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
2124 if (!success) { 2131 if (result->IsFailure()) return result;
2125 return failure;
2126 }
2127 } else { 2132 } else {
2128 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2133 __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
2129 } 2134 }
2130 2135
2131 // Handle call cache miss. 2136 // Handle call cache miss.
2132 __ bind(&miss); 2137 __ bind(&miss);
2133 if (depth != kInvalidProtoDepth) { 2138 if (depth != kInvalidProtoDepth) {
2134 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 2139 __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize));
2135 } 2140 }
2136 2141
(...skipping 28 matching lines...) Expand all
2165 // Get the number of arguments. 2170 // Get the number of arguments.
2166 const int argc = arguments().immediate(); 2171 const int argc = arguments().immediate();
2167 2172
2168 LookupResult lookup; 2173 LookupResult lookup;
2169 LookupPostInterceptor(holder, name, &lookup); 2174 LookupPostInterceptor(holder, name, &lookup);
2170 2175
2171 // Get the receiver from the stack. 2176 // Get the receiver from the stack.
2172 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2177 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2173 2178
2174 CallInterceptorCompiler compiler(this, arguments(), rcx); 2179 CallInterceptorCompiler compiler(this, arguments(), rcx);
2175 Failure* failure; 2180 MaybeObject* result = compiler.Compile(masm(),
2176 bool success = compiler.Compile(masm(), 2181 object,
2177 object, 2182 holder,
2178 holder, 2183 name,
2179 name, 2184 &lookup,
2180 &lookup, 2185 rdx,
2181 rdx, 2186 rbx,
2182 rbx, 2187 rdi,
2183 rdi, 2188 rax,
2184 rax, 2189 &miss);
2185 &miss, 2190 if (result->IsFailure()) return result;
2186 &failure);
2187 if (!success) {
2188 return failure;
2189 }
2190 2191
2191 // Restore receiver. 2192 // Restore receiver.
2192 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2193 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
2193 2194
2194 // Check that the function really is a function. 2195 // Check that the function really is a function.
2195 __ JumpIfSmi(rax, &miss); 2196 __ JumpIfSmi(rax, &miss);
2196 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 2197 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx);
2197 __ j(not_equal, &miss); 2198 __ j(not_equal, &miss);
2198 2199
2199 // Patch the receiver on the stack with the global proxy if 2200 // Patch the receiver on the stack with the global proxy if
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2255 GenerateGlobalReceiverCheck(object, holder, name, &miss); 2256 GenerateGlobalReceiverCheck(object, holder, name, &miss);
2256 2257
2257 GenerateLoadFunctionFromCell(cell, function, &miss); 2258 GenerateLoadFunctionFromCell(cell, function, &miss);
2258 2259
2259 // Patch the receiver on the stack with the global proxy. 2260 // Patch the receiver on the stack with the global proxy.
2260 if (object->IsGlobalObject()) { 2261 if (object->IsGlobalObject()) {
2261 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 2262 __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset));
2262 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 2263 __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx);
2263 } 2264 }
2264 2265
2265 // Setup the context (function already in edi). 2266 // Setup the context (function already in rdi).
2266 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 2267 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
2267 2268
2268 // Jump to the cached code (tail call). 2269 // Jump to the cached code (tail call).
2269 __ IncrementCounter(&Counters::call_global_inline, 1); 2270 __ IncrementCounter(&Counters::call_global_inline, 1);
2270 ASSERT(function->is_compiled()); 2271 ASSERT(function->is_compiled());
2271 Handle<Code> code(function->code());
2272 ParameterCount expected(function->shared()->formal_parameter_count()); 2272 ParameterCount expected(function->shared()->formal_parameter_count());
2273 __ InvokeCode(code, expected, arguments(), 2273 if (V8::UseCrankshaft()) {
2274 RelocInfo::CODE_TARGET, JUMP_FUNCTION); 2274 // TODO(kasperl): For now, we always call indirectly through the
2275 2275 // code field in the function to allow recompilation to take effect
2276 // without changing any of the call sites.
2277 __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
2278 __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION);
2279 } else {
2280 Handle<Code> code(function->code());
2281 __ InvokeCode(code, expected, arguments(),
2282 RelocInfo::CODE_TARGET, JUMP_FUNCTION);
2283 }
2276 // Handle call cache miss. 2284 // Handle call cache miss.
2277 __ bind(&miss); 2285 __ bind(&miss);
2278 __ IncrementCounter(&Counters::call_global_inline_miss, 1); 2286 __ IncrementCounter(&Counters::call_global_inline_miss, 1);
2279 Object* obj; 2287 Object* obj;
2280 { MaybeObject* maybe_obj = GenerateMissBranch(); 2288 { MaybeObject* maybe_obj = GenerateMissBranch();
2281 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2289 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2282 } 2290 }
2283 2291
2284 // Return the generated code. 2292 // Return the generated code.
2285 return GetCode(NORMAL, name); 2293 return GetCode(NORMAL, name);
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2423 // -- rdx : receiver 2431 // -- rdx : receiver
2424 // -- rsp[0] : return address 2432 // -- rsp[0] : return address
2425 // ----------------------------------- 2433 // -----------------------------------
2426 Label miss; 2434 Label miss;
2427 2435
2428 // Check that the map of the global has not changed. 2436 // Check that the map of the global has not changed.
2429 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2437 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2430 Handle<Map>(object->map())); 2438 Handle<Map>(object->map()));
2431 __ j(not_equal, &miss); 2439 __ j(not_equal, &miss);
2432 2440
2441 // Check that the value in the cell is not the hole. If it is, this
2442 // cell could have been deleted and reintroducing the global needs
2443 // to update the property details in the property dictionary of the
2444 // global object. We bail out to the runtime system to do that.
2445 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell));
2446 __ CompareRoot(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
2447 Heap::kTheHoleValueRootIndex);
2448 __ j(equal, &miss);
2449
2433 // Store the value in the cell. 2450 // Store the value in the cell.
2434 __ Move(rcx, Handle<JSGlobalPropertyCell>(cell)); 2451 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rax);
2435 __ movq(FieldOperand(rcx, JSGlobalPropertyCell::kValueOffset), rax);
2436 2452
2437 // Return the value (register rax). 2453 // Return the value (register rax).
2438 __ IncrementCounter(&Counters::named_store_global_inline, 1); 2454 __ IncrementCounter(&Counters::named_store_global_inline, 1);
2439 __ ret(0); 2455 __ ret(0);
2440 2456
2441 // Handle store cache miss. 2457 // Handle store cache miss.
2442 __ bind(&miss); 2458 __ bind(&miss);
2443 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1); 2459 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
2444 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2460 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2445 __ Jump(ic, RelocInfo::CODE_TARGET); 2461 __ Jump(ic, RelocInfo::CODE_TARGET);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
2536 // Handle store cache miss. 2552 // Handle store cache miss.
2537 __ bind(&miss); 2553 __ bind(&miss);
2538 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 2554 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
2539 __ jmp(ic, RelocInfo::CODE_TARGET); 2555 __ jmp(ic, RelocInfo::CODE_TARGET);
2540 2556
2541 // Return the generated code. 2557 // Return the generated code.
2542 return GetCode(NORMAL, NULL); 2558 return GetCode(NORMAL, NULL);
2543 } 2559 }
2544 2560
2545 2561
2562 MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
2563 JSObject* receiver) {
2564 // ----------- S t a t e -------------
2565 // -- rax : value
2566 // -- rcx : key
2567 // -- rdx : receiver
2568 // -- rsp[0] : return address
2569 // -----------------------------------
2570 Label miss;
2571
2572 // Check that the map matches.
2573 __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
2574
2575 // Do the load.
2576 GenerateFastPixelArrayStore(masm(),
2577 rdx,
2578 rcx,
2579 rax,
2580 rdi,
2581 rbx,
2582 true,
2583 false,
2584 &miss,
2585 &miss,
2586 NULL,
2587 &miss);
2588
2589 // Handle store cache miss.
2590 __ bind(&miss);
2591 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
2592 __ jmp(ic, RelocInfo::CODE_TARGET);
2593
2594 // Return the generated code.
2595 return GetCode(NORMAL, NULL);
2596 }
2597
2598
2546 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2599 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2547 JSObject* object, 2600 JSObject* object,
2548 JSObject* last) { 2601 JSObject* last) {
2549 // ----------- S t a t e ------------- 2602 // ----------- S t a t e -------------
2550 // -- rax : receiver 2603 // -- rax : receiver
2551 // -- rcx : name 2604 // -- rcx : name
2552 // -- rsp[0] : return address 2605 // -- rsp[0] : return address
2553 // ----------------------------------- 2606 // -----------------------------------
2554 Label miss; 2607 Label miss;
2555 2608
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
2612 JSObject* object, 2665 JSObject* object,
2613 JSObject* holder, 2666 JSObject* holder,
2614 AccessorInfo* callback) { 2667 AccessorInfo* callback) {
2615 // ----------- S t a t e ------------- 2668 // ----------- S t a t e -------------
2616 // -- rax : receiver 2669 // -- rax : receiver
2617 // -- rcx : name 2670 // -- rcx : name
2618 // -- rsp[0] : return address 2671 // -- rsp[0] : return address
2619 // ----------------------------------- 2672 // -----------------------------------
2620 Label miss; 2673 Label miss;
2621 2674
2622 Failure* failure = Failure::InternalError(); 2675 MaybeObject* result = GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx,
2623 bool success = GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi, 2676 rdi, callback, name, &miss);
2624 callback, name, &miss, &failure); 2677 if (result->IsFailure()) {
2625 if (!success) {
2626 miss.Unuse(); 2678 miss.Unuse();
2627 return failure; 2679 return result;
2628 } 2680 }
2629 2681
2630 __ bind(&miss); 2682 __ bind(&miss);
2631 GenerateLoadMiss(masm(), Code::LOAD_IC); 2683 GenerateLoadMiss(masm(), Code::LOAD_IC);
2632 2684
2633 // Return the generated code. 2685 // Return the generated code.
2634 return GetCode(CALLBACKS, name); 2686 return GetCode(CALLBACKS, name);
2635 } 2687 }
2636 2688
2637 2689
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2776 // -- rsp[0] : return address 2828 // -- rsp[0] : return address
2777 // ----------------------------------- 2829 // -----------------------------------
2778 Label miss; 2830 Label miss;
2779 2831
2780 __ IncrementCounter(&Counters::keyed_load_callback, 1); 2832 __ IncrementCounter(&Counters::keyed_load_callback, 1);
2781 2833
2782 // Check that the name has not changed. 2834 // Check that the name has not changed.
2783 __ Cmp(rax, Handle<String>(name)); 2835 __ Cmp(rax, Handle<String>(name));
2784 __ j(not_equal, &miss); 2836 __ j(not_equal, &miss);
2785 2837
2786 Failure* failure = Failure::InternalError(); 2838 MaybeObject* result = GenerateLoadCallback(receiver, holder, rdx, rax, rbx,
2787 bool success = GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi, 2839 rcx, rdi, callback, name, &miss);
2788 callback, name, &miss, &failure); 2840 if (result->IsFailure()) {
2789 if (!success) {
2790 miss.Unuse(); 2841 miss.Unuse();
2791 return failure; 2842 return result;
2792 } 2843 }
2793 2844
2794 __ bind(&miss); 2845 __ bind(&miss);
2795 2846
2796 __ DecrementCounter(&Counters::keyed_load_callback, 1); 2847 __ DecrementCounter(&Counters::keyed_load_callback, 1);
2797 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2848 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2798 2849
2799 // Return the generated code. 2850 // Return the generated code.
2800 return GetCode(CALLBACKS, name); 2851 return GetCode(CALLBACKS, name);
2801 } 2852 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
2897 // -- rsp[0] : return address 2948 // -- rsp[0] : return address
2898 // ----------------------------------- 2949 // -----------------------------------
2899 Label miss; 2950 Label miss;
2900 2951
2901 __ IncrementCounter(&Counters::keyed_load_string_length, 1); 2952 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
2902 2953
2903 // Check that the name has not changed. 2954 // Check that the name has not changed.
2904 __ Cmp(rax, Handle<String>(name)); 2955 __ Cmp(rax, Handle<String>(name));
2905 __ j(not_equal, &miss); 2956 __ j(not_equal, &miss);
2906 2957
2907 GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss); 2958 GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true);
2908 __ bind(&miss); 2959 __ bind(&miss);
2909 __ DecrementCounter(&Counters::keyed_load_string_length, 1); 2960 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
2910 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2961 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2911 2962
2912 // Return the generated code. 2963 // Return the generated code.
2913 return GetCode(CALLBACKS, name); 2964 return GetCode(CALLBACKS, name);
2914 } 2965 }
2915 2966
2916 2967
2917 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { 2968 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2977 __ ret(0); 3028 __ ret(0);
2978 3029
2979 __ bind(&miss); 3030 __ bind(&miss);
2980 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3031 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2981 3032
2982 // Return the generated code. 3033 // Return the generated code.
2983 return GetCode(NORMAL, NULL); 3034 return GetCode(NORMAL, NULL);
2984 } 3035 }
2985 3036
2986 3037
3038 MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
3039 // ----------- S t a t e -------------
3040 // -- rax : key
3041 // -- rdx : receiver
3042 // -- esp[0] : return address
3043 // -----------------------------------
3044 Label miss;
3045
3046 // Check that the map matches.
3047 __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false);
3048
3049 GenerateFastPixelArrayLoad(masm(),
3050 rdx,
3051 rax,
3052 rbx,
3053 rcx,
3054 rax,
3055 &miss,
3056 &miss,
3057 &miss);
3058
3059 __ bind(&miss);
3060 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3061
3062 // Return the generated code.
3063 return GetCode(NORMAL, NULL);
3064 }
3065
3066
2987 // Specialized stub for constructing objects from functions which only have only 3067 // Specialized stub for constructing objects from functions which only have only
2988 // simple assignments of the form this.x = ...; in their body. 3068 // simple assignments of the form this.x = ...; in their body.
2989 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3069 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
2990 // ----------- S t a t e ------------- 3070 // ----------- S t a t e -------------
2991 // -- rax : argc 3071 // -- rax : argc
2992 // -- rdi : constructor 3072 // -- rdi : constructor
2993 // -- rsp[0] : return address 3073 // -- rsp[0] : return address
2994 // -- rsp[4] : last argument 3074 // -- rsp[4] : last argument
2995 // ----------------------------------- 3075 // -----------------------------------
2996 Label generic_stub_call; 3076 Label generic_stub_call;
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
3108 __ bind(&generic_stub_call); 3188 __ bind(&generic_stub_call);
3109 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 3189 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
3110 Handle<Code> generic_construct_stub(code); 3190 Handle<Code> generic_construct_stub(code);
3111 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 3191 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3112 3192
3113 // Return the generated code. 3193 // Return the generated code.
3114 return GetCode(); 3194 return GetCode();
3115 } 3195 }
3116 3196
3117 3197
3198 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
3199 ExternalArrayType array_type, Code::Flags flags) {
3200 // ----------- S t a t e -------------
3201 // -- rax : key
3202 // -- rdx : receiver
3203 // -- rsp[0] : return address
3204 // -----------------------------------
3205 Label slow;
3206
3207 // Check that the object isn't a smi.
3208 __ JumpIfSmi(rdx, &slow);
3209
3210 // Check that the key is a smi.
3211 __ JumpIfNotSmi(rax, &slow);
3212
3213 // Check that the object is a JS object.
3214 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
3215 __ j(not_equal, &slow);
3216 // Check that the receiver does not require access checks. We need
3217 // to check this explicitly since this generic stub does not perform
3218 // map checks. The map is already in rdx.
3219 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
3220 Immediate(1 << Map::kIsAccessCheckNeeded));
3221 __ j(not_zero, &slow);
3222
3223 // Check that the elements array is the appropriate type of
3224 // ExternalArray.
3225 // rax: index (as a smi)
3226 // rdx: JSObject
3227 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3228 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
3229 Heap::RootIndexForExternalArrayType(array_type));
3230 __ j(not_equal, &slow);
3231
3232 // Check that the index is in range.
3233 __ SmiToInteger32(rcx, rax);
3234 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
3235 // Unsigned comparison catches both negative and too-large values.
3236 __ j(above_equal, &slow);
3237
3238 // rax: index (as a smi)
3239 // rdx: receiver (JSObject)
3240 // rcx: untagged index
3241 // rbx: elements array
3242 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3243 // rbx: base pointer of external storage
3244 switch (array_type) {
3245 case kExternalByteArray:
3246 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
3247 break;
3248 case kExternalUnsignedByteArray:
3249 __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
3250 break;
3251 case kExternalShortArray:
3252 __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
3253 break;
3254 case kExternalUnsignedShortArray:
3255 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
3256 break;
3257 case kExternalIntArray:
3258 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
3259 break;
3260 case kExternalUnsignedIntArray:
3261 __ movl(rcx, Operand(rbx, rcx, times_4, 0));
3262 break;
3263 case kExternalFloatArray:
3264 __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
3265 break;
3266 default:
3267 UNREACHABLE();
3268 break;
3269 }
3270
3271 // rax: index
3272 // rdx: receiver
3273 // For integer array types:
3274 // rcx: value
3275 // For floating-point array type:
3276 // xmm0: value as double.
3277
3278 ASSERT(kSmiValueSize == 32);
3279 if (array_type == kExternalUnsignedIntArray) {
3280 // For the UnsignedInt array type, we need to see whether
3281 // the value can be represented in a Smi. If not, we need to convert
3282 // it to a HeapNumber.
3283 NearLabel box_int;
3284
3285 __ JumpIfUIntNotValidSmiValue(rcx, &box_int);
3286
3287 __ Integer32ToSmi(rax, rcx);
3288 __ ret(0);
3289
3290 __ bind(&box_int);
3291
3292 // Allocate a HeapNumber for the int and perform int-to-double
3293 // conversion.
3294 // The value is zero-extended since we loaded the value from memory
3295 // with movl.
3296 __ cvtqsi2sd(xmm0, rcx);
3297
3298 __ AllocateHeapNumber(rcx, rbx, &slow);
3299 // Set the value.
3300 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3301 __ movq(rax, rcx);
3302 __ ret(0);
3303 } else if (array_type == kExternalFloatArray) {
3304 // For the floating-point array type, we need to always allocate a
3305 // HeapNumber.
3306 __ AllocateHeapNumber(rcx, rbx, &slow);
3307 // Set the value.
3308 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3309 __ movq(rax, rcx);
3310 __ ret(0);
3311 } else {
3312 __ Integer32ToSmi(rax, rcx);
3313 __ ret(0);
3314 }
3315
3316 // Slow case: Jump to runtime.
3317 __ bind(&slow);
3318 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
3319
3320 // ----------- S t a t e -------------
3321 // -- rax : key
3322 // -- rdx : receiver
3323 // -- rsp[0] : return address
3324 // -----------------------------------
3325
3326 __ pop(rbx);
3327 __ push(rdx); // receiver
3328 __ push(rax); // name
3329 __ push(rbx); // return address
3330
3331 // Perform tail call to the entry.
3332 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3333
3334 // Return the generated code.
3335 return GetCode(flags);
3336 }
3337
3338
3339 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
3340 ExternalArrayType array_type, Code::Flags flags) {
3341 // ----------- S t a t e -------------
3342 // -- rax : value
3343 // -- rcx : key
3344 // -- rdx : receiver
3345 // -- rsp[0] : return address
3346 // -----------------------------------
3347 Label slow;
3348
3349 // Check that the object isn't a smi.
3350 __ JumpIfSmi(rdx, &slow);
3351 // Get the map from the receiver.
3352 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
3353 // Check that the receiver does not require access checks. We need
3354 // to do this because this generic stub does not perform map checks.
3355 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
3356 Immediate(1 << Map::kIsAccessCheckNeeded));
3357 __ j(not_zero, &slow);
3358 // Check that the key is a smi.
3359 __ JumpIfNotSmi(rcx, &slow);
3360
3361 // Check that the object is a JS object.
3362 __ CmpInstanceType(rbx, JS_OBJECT_TYPE);
3363 __ j(not_equal, &slow);
3364
3365 // Check that the elements array is the appropriate type of
3366 // ExternalArray.
3367 // rax: value
3368 // rcx: key (a smi)
3369 // rdx: receiver (a JSObject)
3370 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3371 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
3372 Heap::RootIndexForExternalArrayType(array_type));
3373 __ j(not_equal, &slow);
3374
3375 // Check that the index is in range.
3376 __ SmiToInteger32(rdi, rcx); // Untag the index.
3377 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
3378 // Unsigned comparison catches both negative and too-large values.
3379 __ j(above_equal, &slow);
3380
3381 // Handle both smis and HeapNumbers in the fast path. Go to the
3382 // runtime for all other kinds of values.
3383 // rax: value
3384 // rcx: key (a smi)
3385 // rdx: receiver (a JSObject)
3386 // rbx: elements array
3387 // rdi: untagged key
3388 NearLabel check_heap_number;
3389 __ JumpIfNotSmi(rax, &check_heap_number);
3390 // No more branches to slow case on this path. Key and receiver not needed.
3391 __ SmiToInteger32(rdx, rax);
3392 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3393 // rbx: base pointer of external storage
3394 switch (array_type) {
3395 case kExternalByteArray:
3396 case kExternalUnsignedByteArray:
3397 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3398 break;
3399 case kExternalShortArray:
3400 case kExternalUnsignedShortArray:
3401 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
3402 break;
3403 case kExternalIntArray:
3404 case kExternalUnsignedIntArray:
3405 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
3406 break;
3407 case kExternalFloatArray:
3408 // Need to perform int-to-float conversion.
3409 __ cvtlsi2ss(xmm0, rdx);
3410 __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
3411 break;
3412 default:
3413 UNREACHABLE();
3414 break;
3415 }
3416 __ ret(0);
3417
3418 __ bind(&check_heap_number);
3419 // rax: value
3420 // rcx: key (a smi)
3421 // rdx: receiver (a JSObject)
3422 // rbx: elements array
3423 // rdi: untagged key
3424 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
3425 __ j(not_equal, &slow);
3426 // No more branches to slow case on this path.
3427
3428 // The WebGL specification leaves the behavior of storing NaN and
3429 // +/-Infinity into integer arrays basically undefined. For more
3430 // reproducible behavior, convert these to zero.
3431 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
3432 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3433 // rdi: untagged index
3434 // rbx: base pointer of external storage
3435 // top of FPU stack: value
3436 if (array_type == kExternalFloatArray) {
3437 __ cvtsd2ss(xmm0, xmm0);
3438 __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
3439 __ ret(0);
3440 } else {
3441 // Perform float-to-int conversion with truncation (round-to-zero)
3442 // behavior.
3443
3444 // Convert to int32 and store the low byte/word.
3445 // If the value is NaN or +/-infinity, the result is 0x80000000,
3446 // which is automatically zero when taken mod 2^n, n < 32.
3447 // rdx: value (converted to an untagged integer)
3448 // rdi: untagged index
3449 // rbx: base pointer of external storage
3450 switch (array_type) {
3451 case kExternalByteArray:
3452 case kExternalUnsignedByteArray:
3453 __ cvttsd2si(rdx, xmm0);
3454 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3455 break;
3456 case kExternalShortArray:
3457 case kExternalUnsignedShortArray:
3458 __ cvttsd2si(rdx, xmm0);
3459 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
3460 break;
3461 case kExternalIntArray:
3462 case kExternalUnsignedIntArray: {
3463 // Convert to int64, so that NaN and infinities become
3464 // 0x8000000000000000, which is zero mod 2^32.
3465 __ cvttsd2siq(rdx, xmm0);
3466 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
3467 break;
3468 }
3469 default:
3470 UNREACHABLE();
3471 break;
3472 }
3473 __ ret(0);
3474 }
3475
3476 // Slow case: call runtime.
3477 __ bind(&slow);
3478
3479 // ----------- S t a t e -------------
3480 // -- rax : value
3481 // -- rcx : key
3482 // -- rdx : receiver
3483 // -- rsp[0] : return address
3484 // -----------------------------------
3485
3486 __ pop(rbx);
3487 __ push(rdx); // receiver
3488 __ push(rcx); // key
3489 __ push(rax); // value
3490 __ push(rbx); // return address
3491
3492 // Do tail-call to runtime routine.
3493 __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
3494
3495 return GetCode(flags);
3496 }
3497
3118 #undef __ 3498 #undef __
3119 3499
3120 } } // namespace v8::internal 3500 } } // namespace v8::internal
3121 3501
3122 #endif // V8_TARGET_ARCH_X64 3502 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | src/x64/virtual-frame-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698