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

Side by Side Diff: src/ia32/stub-cache-ia32.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/ia32/macro-assembler-ia32.cc ('k') | src/ia32/virtual-frame-ia32.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 309 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 ASSERT(kNotStringTag != 0); 320 ASSERT(kNotStringTag != 0);
321 __ test(scratch, Immediate(kNotStringTag)); 321 __ test(scratch, Immediate(kNotStringTag));
322 __ j(not_zero, non_string_object, not_taken); 322 __ j(not_zero, non_string_object, not_taken);
323 } 323 }
324 324
325 325
326 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 326 void StubCompiler::GenerateLoadStringLength(MacroAssembler* masm,
327 Register receiver, 327 Register receiver,
328 Register scratch1, 328 Register scratch1,
329 Register scratch2, 329 Register scratch2,
330 Label* miss) { 330 Label* miss,
331 bool support_wrappers) {
331 Label check_wrapper; 332 Label check_wrapper;
332 333
333 // Check if the object is a string leaving the instance type in the 334 // Check if the object is a string leaving the instance type in the
334 // scratch register. 335 // scratch register.
335 GenerateStringCheck(masm, receiver, scratch1, miss, &check_wrapper); 336 GenerateStringCheck(masm, receiver, scratch1, miss,
337 support_wrappers ? &check_wrapper : miss);
336 338
337 // Load length from the string and convert to a smi. 339 // Load length from the string and convert to a smi.
338 __ mov(eax, FieldOperand(receiver, String::kLengthOffset)); 340 __ mov(eax, FieldOperand(receiver, String::kLengthOffset));
339 __ ret(0); 341 __ ret(0);
340 342
341 // Check if the object is a JSValue wrapper. 343 if (support_wrappers) {
342 __ bind(&check_wrapper); 344 // Check if the object is a JSValue wrapper.
343 __ cmp(scratch1, JS_VALUE_TYPE); 345 __ bind(&check_wrapper);
344 __ j(not_equal, miss, not_taken); 346 __ cmp(scratch1, JS_VALUE_TYPE);
347 __ j(not_equal, miss, not_taken);
345 348
346 // Check if the wrapped value is a string and load the length 349 // Check if the wrapped value is a string and load the length
347 // directly if it is. 350 // directly if it is.
348 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); 351 __ mov(scratch2, FieldOperand(receiver, JSValue::kValueOffset));
349 GenerateStringCheck(masm, scratch2, scratch1, miss, miss); 352 GenerateStringCheck(masm, scratch2, scratch1, miss, miss);
350 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset)); 353 __ mov(eax, FieldOperand(scratch2, String::kLengthOffset));
351 __ ret(0); 354 __ ret(0);
355 }
352 } 356 }
353 357
354 358
355 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 359 void StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm,
356 Register receiver, 360 Register receiver,
357 Register scratch1, 361 Register scratch1,
358 Register scratch2, 362 Register scratch2,
359 Label* miss_label) { 363 Label* miss_label) {
360 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 364 __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label);
361 __ mov(eax, Operand(scratch1)); 365 __ mov(eax, Operand(scratch1));
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal 448 // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal
445 // frame. 449 // frame.
446 // ----------------------------------- 450 // -----------------------------------
447 __ pop(scratch); 451 __ pop(scratch);
448 __ add(Operand(esp), Immediate(kPointerSize * kFastApiCallArguments)); 452 __ add(Operand(esp), Immediate(kPointerSize * kFastApiCallArguments));
449 __ push(scratch); 453 __ push(scratch);
450 } 454 }
451 455
452 456
453 // Generates call to API function. 457 // Generates call to API function.
454 static bool GenerateFastApiCall(MacroAssembler* masm, 458 static MaybeObject* GenerateFastApiCall(MacroAssembler* masm,
455 const CallOptimization& optimization, 459 const CallOptimization& optimization,
456 int argc, 460 int argc) {
457 Failure** failure) {
458 // ----------- S t a t e ------------- 461 // ----------- S t a t e -------------
459 // -- esp[0] : return address 462 // -- esp[0] : return address
460 // -- esp[4] : object passing the type check 463 // -- esp[4] : object passing the type check
461 // (last fast api call extra argument, 464 // (last fast api call extra argument,
462 // set by CheckPrototypes) 465 // set by CheckPrototypes)
463 // -- esp[8] : api function 466 // -- esp[8] : api function
464 // (first fast api call extra argument) 467 // (first fast api call extra argument)
465 // -- esp[12] : api call data 468 // -- esp[12] : api call data
466 // -- esp[16] : last argument 469 // -- esp[16] : last argument
467 // -- ... 470 // -- ...
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 __ Set(ApiParameterOperand(4), Immediate(0)); 512 __ Set(ApiParameterOperand(4), Immediate(0));
510 513
511 // v8::InvocationCallback's argument. 514 // v8::InvocationCallback's argument.
512 __ lea(eax, ApiParameterOperand(1)); 515 __ lea(eax, ApiParameterOperand(1));
513 __ mov(ApiParameterOperand(0), eax); 516 __ mov(ApiParameterOperand(0), eax);
514 517
515 // Emitting a stub call may try to allocate (if the code is not 518 // Emitting a stub call may try to allocate (if the code is not
516 // already generated). Do not allow the assembler to perform a 519 // already generated). Do not allow the assembler to perform a
517 // garbage collection but instead return the allocation failure 520 // garbage collection but instead return the allocation failure
518 // object. 521 // object.
519 MaybeObject* result = 522 return masm->TryCallApiFunctionAndReturn(&fun,
520 masm->TryCallApiFunctionAndReturn(&fun, argc + kFastApiCallArguments + 1); 523 argc + kFastApiCallArguments + 1);
521 if (result->IsFailure()) {
522 *failure = Failure::cast(result);
523 return false;
524 }
525 return true;
526 } 524 }
527 525
528 526
529 class CallInterceptorCompiler BASE_EMBEDDED { 527 class CallInterceptorCompiler BASE_EMBEDDED {
530 public: 528 public:
531 CallInterceptorCompiler(StubCompiler* stub_compiler, 529 CallInterceptorCompiler(StubCompiler* stub_compiler,
532 const ParameterCount& arguments, 530 const ParameterCount& arguments,
533 Register name) 531 Register name)
534 : stub_compiler_(stub_compiler), 532 : stub_compiler_(stub_compiler),
535 arguments_(arguments), 533 arguments_(arguments),
536 name_(name) {} 534 name_(name) {}
537 535
538 bool Compile(MacroAssembler* masm, 536 MaybeObject* Compile(MacroAssembler* masm,
539 JSObject* object, 537 JSObject* object,
540 JSObject* holder, 538 JSObject* holder,
541 String* name, 539 String* name,
542 LookupResult* lookup, 540 LookupResult* lookup,
543 Register receiver, 541 Register receiver,
544 Register scratch1, 542 Register scratch1,
545 Register scratch2, 543 Register scratch2,
546 Register scratch3, 544 Register scratch3,
547 Label* miss, 545 Label* miss) {
548 Failure** failure) {
549 ASSERT(holder->HasNamedInterceptor()); 546 ASSERT(holder->HasNamedInterceptor());
550 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 547 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
551 548
552 // Check that the receiver isn't a smi. 549 // Check that the receiver isn't a smi.
553 __ test(receiver, Immediate(kSmiTagMask)); 550 __ test(receiver, Immediate(kSmiTagMask));
554 __ j(zero, miss, not_taken); 551 __ j(zero, miss, not_taken);
555 552
556 CallOptimization optimization(lookup); 553 CallOptimization optimization(lookup);
557 554
558 if (optimization.is_constant_call()) { 555 if (optimization.is_constant_call()) {
559 return CompileCacheable(masm, 556 return CompileCacheable(masm,
560 object, 557 object,
561 receiver, 558 receiver,
562 scratch1, 559 scratch1,
563 scratch2, 560 scratch2,
564 scratch3, 561 scratch3,
565 holder, 562 holder,
566 lookup, 563 lookup,
567 name, 564 name,
568 optimization, 565 optimization,
569 miss, 566 miss);
570 failure);
571 } else { 567 } else {
572 CompileRegular(masm, 568 CompileRegular(masm,
573 object, 569 object,
574 receiver, 570 receiver,
575 scratch1, 571 scratch1,
576 scratch2, 572 scratch2,
577 scratch3, 573 scratch3,
578 name, 574 name,
579 holder, 575 holder,
580 miss); 576 miss);
581 return true; 577 return Heap::undefined_value(); // Success.
582 } 578 }
583 } 579 }
584 580
585 private: 581 private:
586 bool CompileCacheable(MacroAssembler* masm, 582 MaybeObject* CompileCacheable(MacroAssembler* masm,
587 JSObject* object, 583 JSObject* object,
588 Register receiver, 584 Register receiver,
589 Register scratch1, 585 Register scratch1,
590 Register scratch2, 586 Register scratch2,
591 Register scratch3, 587 Register scratch3,
592 JSObject* interceptor_holder, 588 JSObject* interceptor_holder,
593 LookupResult* lookup, 589 LookupResult* lookup,
594 String* name, 590 String* name,
595 const CallOptimization& optimization, 591 const CallOptimization& optimization,
596 Label* miss_label, 592 Label* miss_label) {
597 Failure** failure) {
598 ASSERT(optimization.is_constant_call()); 593 ASSERT(optimization.is_constant_call());
599 ASSERT(!lookup->holder()->IsGlobalObject()); 594 ASSERT(!lookup->holder()->IsGlobalObject());
600 595
601 int depth1 = kInvalidProtoDepth; 596 int depth1 = kInvalidProtoDepth;
602 int depth2 = kInvalidProtoDepth; 597 int depth2 = kInvalidProtoDepth;
603 bool can_do_fast_api_call = false; 598 bool can_do_fast_api_call = false;
604 if (optimization.is_simple_api_call() && 599 if (optimization.is_simple_api_call() &&
605 !lookup->holder()->IsGlobalObject()) { 600 !lookup->holder()->IsGlobalObject()) {
606 depth1 = 601 depth1 =
607 optimization.GetPrototypeDepthOfExpectedType(object, 602 optimization.GetPrototypeDepthOfExpectedType(object,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 } else { 644 } else {
650 // CheckPrototypes has a side effect of fetching a 'holder' 645 // CheckPrototypes has a side effect of fetching a 'holder'
651 // for API (object which is instanceof for the signature). It's 646 // for API (object which is instanceof for the signature). It's
652 // safe to omit it here, as if present, it should be fetched 647 // safe to omit it here, as if present, it should be fetched
653 // by the previous CheckPrototypes. 648 // by the previous CheckPrototypes.
654 ASSERT(depth2 == kInvalidProtoDepth); 649 ASSERT(depth2 == kInvalidProtoDepth);
655 } 650 }
656 651
657 // Invoke function. 652 // Invoke function.
658 if (can_do_fast_api_call) { 653 if (can_do_fast_api_call) {
659 bool success = GenerateFastApiCall(masm, optimization, 654 MaybeObject* result =
660 arguments_.immediate(), failure); 655 GenerateFastApiCall(masm, optimization, arguments_.immediate());
661 if (!success) { 656 if (result->IsFailure()) return result;
662 return false;
663 }
664 } else { 657 } else {
665 __ InvokeFunction(optimization.constant_function(), arguments_, 658 __ InvokeFunction(optimization.constant_function(), arguments_,
666 JUMP_FUNCTION); 659 JUMP_FUNCTION);
667 } 660 }
668 661
669 // Deferred code for fast API call case---clean preallocated space. 662 // Deferred code for fast API call case---clean preallocated space.
670 if (can_do_fast_api_call) { 663 if (can_do_fast_api_call) {
671 __ bind(&miss_cleanup); 664 __ bind(&miss_cleanup);
672 FreeSpaceForFastApiCall(masm, scratch1); 665 FreeSpaceForFastApiCall(masm, scratch1);
673 __ jmp(miss_label); 666 __ jmp(miss_label);
674 } 667 }
675 668
676 // Invoke a regular function. 669 // Invoke a regular function.
677 __ bind(&regular_invoke); 670 __ bind(&regular_invoke);
678 if (can_do_fast_api_call) { 671 if (can_do_fast_api_call) {
679 FreeSpaceForFastApiCall(masm, scratch1); 672 FreeSpaceForFastApiCall(masm, scratch1);
680 } 673 }
681 674
682 return true; 675 return Heap::undefined_value(); // Success.
683 } 676 }
684 677
685 void CompileRegular(MacroAssembler* masm, 678 void CompileRegular(MacroAssembler* masm,
686 JSObject* object, 679 JSObject* object,
687 Register receiver, 680 Register receiver,
688 Register scratch1, 681 Register scratch1,
689 Register scratch2, 682 Register scratch2,
690 Register scratch3, 683 Register scratch3,
691 String* name, 684 String* name,
692 JSObject* interceptor_holder, 685 JSObject* interceptor_holder,
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
1050 Register reg = 1043 Register reg =
1051 CheckPrototypes(object, receiver, holder, 1044 CheckPrototypes(object, receiver, holder,
1052 scratch1, scratch2, scratch3, name, miss); 1045 scratch1, scratch2, scratch3, name, miss);
1053 1046
1054 // Get the value from the properties. 1047 // Get the value from the properties.
1055 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); 1048 GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
1056 __ ret(0); 1049 __ ret(0);
1057 } 1050 }
1058 1051
1059 1052
1060 bool StubCompiler::GenerateLoadCallback(JSObject* object, 1053 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
1061 JSObject* holder, 1054 JSObject* holder,
1062 Register receiver, 1055 Register receiver,
1063 Register name_reg, 1056 Register name_reg,
1064 Register scratch1, 1057 Register scratch1,
1065 Register scratch2, 1058 Register scratch2,
1066 Register scratch3, 1059 Register scratch3,
1067 AccessorInfo* callback, 1060 AccessorInfo* callback,
1068 String* name, 1061 String* name,
1069 Label* miss, 1062 Label* miss) {
1070 Failure** failure) {
1071 // Check that the receiver isn't a smi. 1063 // Check that the receiver isn't a smi.
1072 __ test(receiver, Immediate(kSmiTagMask)); 1064 __ test(receiver, Immediate(kSmiTagMask));
1073 __ j(zero, miss, not_taken); 1065 __ j(zero, miss, not_taken);
1074 1066
1075 // Check that the maps haven't changed. 1067 // Check that the maps haven't changed.
1076 Register reg = 1068 Register reg =
1077 CheckPrototypes(object, receiver, holder, scratch1, 1069 CheckPrototypes(object, receiver, holder, scratch1,
1078 scratch2, scratch3, name, miss); 1070 scratch2, scratch3, name, miss);
1079 1071
1080 Handle<AccessorInfo> callback_handle(callback); 1072 Handle<AccessorInfo> callback_handle(callback);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 1107
1116 __ PrepareCallApiFunction(kApiArgc, eax); 1108 __ PrepareCallApiFunction(kApiArgc, eax);
1117 __ mov(ApiParameterOperand(0), ebx); // name. 1109 __ mov(ApiParameterOperand(0), ebx); // name.
1118 __ add(Operand(ebx), Immediate(kPointerSize)); 1110 __ add(Operand(ebx), Immediate(kPointerSize));
1119 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. 1111 __ mov(ApiParameterOperand(1), ebx); // arguments pointer.
1120 1112
1121 // Emitting a stub call may try to allocate (if the code is not 1113 // Emitting a stub call may try to allocate (if the code is not
1122 // already generated). Do not allow the assembler to perform a 1114 // already generated). Do not allow the assembler to perform a
1123 // garbage collection but instead return the allocation failure 1115 // garbage collection but instead return the allocation failure
1124 // object. 1116 // object.
1125 MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); 1117 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
1126 if (result->IsFailure()) {
1127 *failure = Failure::cast(result);
1128 return false;
1129 }
1130
1131 return true;
1132 } 1118 }
1133 1119
1134 1120
1135 void StubCompiler::GenerateLoadConstant(JSObject* object, 1121 void StubCompiler::GenerateLoadConstant(JSObject* object,
1136 JSObject* holder, 1122 JSObject* holder,
1137 Register receiver, 1123 Register receiver,
1138 Register scratch1, 1124 Register scratch1,
1139 Register scratch2, 1125 Register scratch2,
1140 Register scratch3, 1126 Register scratch3,
1141 Object* value, 1127 Object* value,
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 Immediate(Handle<SharedFunctionInfo>(function->shared()))); 1341 Immediate(Handle<SharedFunctionInfo>(function->shared())));
1356 __ j(not_equal, miss, not_taken); 1342 __ j(not_equal, miss, not_taken);
1357 } else { 1343 } else {
1358 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); 1344 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function)));
1359 __ j(not_equal, miss, not_taken); 1345 __ j(not_equal, miss, not_taken);
1360 } 1346 }
1361 } 1347 }
1362 1348
1363 1349
1364 MaybeObject* CallStubCompiler::GenerateMissBranch() { 1350 MaybeObject* CallStubCompiler::GenerateMissBranch() {
1351 MaybeObject* maybe_obj = StubCache::ComputeCallMiss(arguments().immediate(),
1352 kind_);
1365 Object* obj; 1353 Object* obj;
1366 { MaybeObject* maybe_obj = 1354 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1367 StubCache::ComputeCallMiss(arguments().immediate(), kind_);
1368 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1369 }
1370 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET); 1355 __ jmp(Handle<Code>(Code::cast(obj)), RelocInfo::CODE_TARGET);
1371 return obj; 1356 return obj;
1372 } 1357 }
1373 1358
1374 1359
1375 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField( 1360 MUST_USE_RESULT MaybeObject* CallStubCompiler::CompileCallField(
1376 JSObject* object, 1361 JSObject* object,
1377 JSObject* holder, 1362 JSObject* holder,
1378 int index, 1363 int index,
1379 String* name) { 1364 String* name) {
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
1679 // -- ... 1664 // -- ...
1680 // -- esp[(argc + 1) * 4] : receiver 1665 // -- esp[(argc + 1) * 4] : receiver
1681 // ----------------------------------- 1666 // -----------------------------------
1682 1667
1683 // If object is not a string, bail out to regular call. 1668 // If object is not a string, bail out to regular call.
1684 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); 1669 if (!object->IsString() || cell != NULL) return Heap::undefined_value();
1685 1670
1686 const int argc = arguments().immediate(); 1671 const int argc = arguments().immediate();
1687 1672
1688 Label miss; 1673 Label miss;
1674 Label name_miss;
1689 Label index_out_of_range; 1675 Label index_out_of_range;
1676 Label* index_out_of_range_label = &index_out_of_range;
1690 1677
1691 GenerateNameCheck(name, &miss); 1678 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
1679 index_out_of_range_label = &miss;
1680 }
1681
1682 GenerateNameCheck(name, &name_miss);
1692 1683
1693 // Check that the maps starting from the prototype haven't changed. 1684 // Check that the maps starting from the prototype haven't changed.
1694 GenerateDirectLoadGlobalFunctionPrototype(masm(), 1685 GenerateDirectLoadGlobalFunctionPrototype(masm(),
1695 Context::STRING_FUNCTION_INDEX, 1686 Context::STRING_FUNCTION_INDEX,
1696 eax, 1687 eax,
1697 &miss); 1688 &miss);
1698 ASSERT(object != holder); 1689 ASSERT(object != holder);
1699 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 1690 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
1700 ebx, edx, edi, name, &miss); 1691 ebx, edx, edi, name, &miss);
1701 1692
1702 Register receiver = ebx; 1693 Register receiver = ebx;
1703 Register index = edi; 1694 Register index = edi;
1704 Register scratch = edx; 1695 Register scratch = edx;
1705 Register result = eax; 1696 Register result = eax;
1706 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 1697 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
1707 if (argc > 0) { 1698 if (argc > 0) {
1708 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 1699 __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
1709 } else { 1700 } else {
1710 __ Set(index, Immediate(Factory::undefined_value())); 1701 __ Set(index, Immediate(Factory::undefined_value()));
1711 } 1702 }
1712 1703
1713 StringCharCodeAtGenerator char_code_at_generator(receiver, 1704 StringCharCodeAtGenerator char_code_at_generator(receiver,
1714 index, 1705 index,
1715 scratch, 1706 scratch,
1716 result, 1707 result,
1717 &miss, // When not a string. 1708 &miss, // When not a string.
1718 &miss, // When not a number. 1709 &miss, // When not a number.
1719 &index_out_of_range, 1710 index_out_of_range_label,
1720 STRING_INDEX_IS_NUMBER); 1711 STRING_INDEX_IS_NUMBER);
1721 char_code_at_generator.GenerateFast(masm()); 1712 char_code_at_generator.GenerateFast(masm());
1722 __ ret((argc + 1) * kPointerSize); 1713 __ ret((argc + 1) * kPointerSize);
1723 1714
1724 StubRuntimeCallHelper call_helper; 1715 StubRuntimeCallHelper call_helper;
1725 char_code_at_generator.GenerateSlow(masm(), call_helper); 1716 char_code_at_generator.GenerateSlow(masm(), call_helper);
1726 1717
1727 __ bind(&index_out_of_range); 1718 if (index_out_of_range.is_linked()) {
1728 __ Set(eax, Immediate(Factory::nan_value())); 1719 __ bind(&index_out_of_range);
1729 __ ret((argc + 1) * kPointerSize); 1720 __ Set(eax, Immediate(Factory::nan_value()));
1721 __ ret((argc + 1) * kPointerSize);
1722 }
1730 1723
1731 __ bind(&miss); 1724 __ bind(&miss);
1725 // Restore function name in ecx.
1726 __ Set(ecx, Immediate(Handle<String>(name)));
1727 __ bind(&name_miss);
1732 Object* obj; 1728 Object* obj;
1733 { MaybeObject* maybe_obj = GenerateMissBranch(); 1729 { MaybeObject* maybe_obj = GenerateMissBranch();
1734 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1730 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1735 } 1731 }
1736 1732
1737 // Return the generated code. 1733 // Return the generated code.
1738 return GetCode(function); 1734 return GetCode(function);
1739 } 1735 }
1740 1736
1741 1737
(...skipping 10 matching lines...) Expand all
1752 // -- ... 1748 // -- ...
1753 // -- esp[(argc + 1) * 4] : receiver 1749 // -- esp[(argc + 1) * 4] : receiver
1754 // ----------------------------------- 1750 // -----------------------------------
1755 1751
1756 // If object is not a string, bail out to regular call. 1752 // If object is not a string, bail out to regular call.
1757 if (!object->IsString() || cell != NULL) return Heap::undefined_value(); 1753 if (!object->IsString() || cell != NULL) return Heap::undefined_value();
1758 1754
1759 const int argc = arguments().immediate(); 1755 const int argc = arguments().immediate();
1760 1756
1761 Label miss; 1757 Label miss;
1758 Label name_miss;
1762 Label index_out_of_range; 1759 Label index_out_of_range;
1760 Label* index_out_of_range_label = &index_out_of_range;
1763 1761
1764 GenerateNameCheck(name, &miss); 1762 if (kind_ == Code::CALL_IC && extra_ic_state_ == DEFAULT_STRING_STUB) {
1763 index_out_of_range_label = &miss;
1764 }
1765
1766 GenerateNameCheck(name, &name_miss);
1765 1767
1766 // Check that the maps starting from the prototype haven't changed. 1768 // Check that the maps starting from the prototype haven't changed.
1767 GenerateDirectLoadGlobalFunctionPrototype(masm(), 1769 GenerateDirectLoadGlobalFunctionPrototype(masm(),
1768 Context::STRING_FUNCTION_INDEX, 1770 Context::STRING_FUNCTION_INDEX,
1769 eax, 1771 eax,
1770 &miss); 1772 &miss);
1771 ASSERT(object != holder); 1773 ASSERT(object != holder);
1772 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 1774 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
1773 ebx, edx, edi, name, &miss); 1775 ebx, edx, edi, name, &miss);
1774 1776
1775 Register receiver = eax; 1777 Register receiver = eax;
1776 Register index = edi; 1778 Register index = edi;
1777 Register scratch1 = ebx; 1779 Register scratch1 = ebx;
1778 Register scratch2 = edx; 1780 Register scratch2 = edx;
1779 Register result = eax; 1781 Register result = eax;
1780 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize)); 1782 __ mov(receiver, Operand(esp, (argc + 1) * kPointerSize));
1781 if (argc > 0) { 1783 if (argc > 0) {
1782 __ mov(index, Operand(esp, (argc - 0) * kPointerSize)); 1784 __ mov(index, Operand(esp, (argc - 0) * kPointerSize));
1783 } else { 1785 } else {
1784 __ Set(index, Immediate(Factory::undefined_value())); 1786 __ Set(index, Immediate(Factory::undefined_value()));
1785 } 1787 }
1786 1788
1787 StringCharAtGenerator char_at_generator(receiver, 1789 StringCharAtGenerator char_at_generator(receiver,
1788 index, 1790 index,
1789 scratch1, 1791 scratch1,
1790 scratch2, 1792 scratch2,
1791 result, 1793 result,
1792 &miss, // When not a string. 1794 &miss, // When not a string.
1793 &miss, // When not a number. 1795 &miss, // When not a number.
1794 &index_out_of_range, 1796 index_out_of_range_label,
1795 STRING_INDEX_IS_NUMBER); 1797 STRING_INDEX_IS_NUMBER);
1796 char_at_generator.GenerateFast(masm()); 1798 char_at_generator.GenerateFast(masm());
1797 __ ret((argc + 1) * kPointerSize); 1799 __ ret((argc + 1) * kPointerSize);
1798 1800
1799 StubRuntimeCallHelper call_helper; 1801 StubRuntimeCallHelper call_helper;
1800 char_at_generator.GenerateSlow(masm(), call_helper); 1802 char_at_generator.GenerateSlow(masm(), call_helper);
1801 1803
1802 __ bind(&index_out_of_range); 1804 if (index_out_of_range.is_linked()) {
1803 __ Set(eax, Immediate(Factory::empty_string())); 1805 __ bind(&index_out_of_range);
1804 __ ret((argc + 1) * kPointerSize); 1806 __ Set(eax, Immediate(Factory::empty_string()));
1807 __ ret((argc + 1) * kPointerSize);
1808 }
1805 1809
1806 __ bind(&miss); 1810 __ bind(&miss);
1811 // Restore function name in ecx.
1812 __ Set(ecx, Immediate(Handle<String>(name)));
1813 __ bind(&name_miss);
1807 Object* obj; 1814 Object* obj;
1808 { MaybeObject* maybe_obj = GenerateMissBranch(); 1815 { MaybeObject* maybe_obj = GenerateMissBranch();
1809 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 1816 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1810 } 1817 }
1811 1818
1812 // Return the generated code. 1819 // Return the generated code.
1813 return GetCode(function); 1820 return GetCode(function);
1814 } 1821 }
1815 1822
1816 1823
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
2253 ebx, edx, edi, name, &miss); 2260 ebx, edx, edi, name, &miss);
2254 } 2261 }
2255 break; 2262 break;
2256 } 2263 }
2257 2264
2258 default: 2265 default:
2259 UNREACHABLE(); 2266 UNREACHABLE();
2260 } 2267 }
2261 2268
2262 if (depth != kInvalidProtoDepth) { 2269 if (depth != kInvalidProtoDepth) {
2263 Failure* failure;
2264 // Move the return address on top of the stack. 2270 // Move the return address on top of the stack.
2265 __ mov(eax, Operand(esp, 3 * kPointerSize)); 2271 __ mov(eax, Operand(esp, 3 * kPointerSize));
2266 __ mov(Operand(esp, 0 * kPointerSize), eax); 2272 __ mov(Operand(esp, 0 * kPointerSize), eax);
2267 2273
2268 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains 2274 // esp[2 * kPointerSize] is uninitialized, esp[3 * kPointerSize] contains
2269 // duplicate of return address and will be overwritten. 2275 // duplicate of return address and will be overwritten.
2270 bool success = GenerateFastApiCall(masm(), optimization, argc, &failure); 2276 MaybeObject* result = GenerateFastApiCall(masm(), optimization, argc);
2271 if (!success) { 2277 if (result->IsFailure()) return result;
2272 return failure;
2273 }
2274 } else { 2278 } else {
2275 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2279 __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
2276 } 2280 }
2277 2281
2278 // Handle call cache miss. 2282 // Handle call cache miss.
2279 __ bind(&miss); 2283 __ bind(&miss);
2280 if (depth != kInvalidProtoDepth) { 2284 if (depth != kInvalidProtoDepth) {
2281 __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); 2285 __ add(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
2282 } 2286 }
2283 __ bind(&miss_in_smi_check); 2287 __ bind(&miss_in_smi_check);
(...skipping 24 matching lines...) Expand all
2308 // Get the number of arguments. 2312 // Get the number of arguments.
2309 const int argc = arguments().immediate(); 2313 const int argc = arguments().immediate();
2310 2314
2311 LookupResult lookup; 2315 LookupResult lookup;
2312 LookupPostInterceptor(holder, name, &lookup); 2316 LookupPostInterceptor(holder, name, &lookup);
2313 2317
2314 // Get the receiver from the stack. 2318 // Get the receiver from the stack.
2315 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2319 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2316 2320
2317 CallInterceptorCompiler compiler(this, arguments(), ecx); 2321 CallInterceptorCompiler compiler(this, arguments(), ecx);
2318 Failure* failure; 2322 MaybeObject* result = compiler.Compile(masm(),
2319 bool success = compiler.Compile(masm(), 2323 object,
2320 object, 2324 holder,
2321 holder, 2325 name,
2322 name, 2326 &lookup,
2323 &lookup, 2327 edx,
2324 edx, 2328 ebx,
2325 ebx, 2329 edi,
2326 edi, 2330 eax,
2327 eax, 2331 &miss);
2328 &miss, 2332 if (result->IsFailure()) return result;
2329 &failure);
2330 if (!success) {
2331 return failure;
2332 }
2333 2333
2334 // Restore receiver. 2334 // Restore receiver.
2335 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2335 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2336 2336
2337 // Check that the function really is a function. 2337 // Check that the function really is a function.
2338 __ test(eax, Immediate(kSmiTagMask)); 2338 __ test(eax, Immediate(kSmiTagMask));
2339 __ j(zero, &miss, not_taken); 2339 __ j(zero, &miss, not_taken);
2340 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2340 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2341 __ j(not_equal, &miss, not_taken); 2341 __ j(not_equal, &miss, not_taken);
2342 2342
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
2576 // -- edx : receiver 2576 // -- edx : receiver
2577 // -- esp[0] : return address 2577 // -- esp[0] : return address
2578 // ----------------------------------- 2578 // -----------------------------------
2579 Label miss; 2579 Label miss;
2580 2580
2581 // Check that the map of the global has not changed. 2581 // Check that the map of the global has not changed.
2582 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2582 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2583 Immediate(Handle<Map>(object->map()))); 2583 Immediate(Handle<Map>(object->map())));
2584 __ j(not_equal, &miss, not_taken); 2584 __ j(not_equal, &miss, not_taken);
2585 2585
2586 // Store the value in the cell. 2586
2587 // Compute the cell operand to use.
2588 Operand cell_operand = Operand::Cell(Handle<JSGlobalPropertyCell>(cell));
2587 if (Serializer::enabled()) { 2589 if (Serializer::enabled()) {
2588 __ mov(ecx, Immediate(Handle<JSGlobalPropertyCell>(cell))); 2590 __ mov(ecx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
2589 __ mov(FieldOperand(ecx, JSGlobalPropertyCell::kValueOffset), eax); 2591 cell_operand = FieldOperand(ecx, JSGlobalPropertyCell::kValueOffset);
2590 } else {
2591 __ mov(Operand::Cell(Handle<JSGlobalPropertyCell>(cell)), eax);
2592 } 2592 }
2593 2593
2594 // Check that the value in the cell is not the hole. If it is, this
2595 // cell could have been deleted and reintroducing the global needs
2596 // to update the property details in the property dictionary of the
2597 // global object. We bail out to the runtime system to do that.
2598 __ cmp(cell_operand, Factory::the_hole_value());
2599 __ j(equal, &miss);
2600
2601 // Store the value in the cell.
2602 __ mov(cell_operand, eax);
2603
2594 // Return the value (register eax). 2604 // Return the value (register eax).
2595 __ IncrementCounter(&Counters::named_store_global_inline, 1); 2605 __ IncrementCounter(&Counters::named_store_global_inline, 1);
2596 __ ret(0); 2606 __ ret(0);
2597 2607
2598 // Handle store cache miss. 2608 // Handle store cache miss.
2599 __ bind(&miss); 2609 __ bind(&miss);
2600 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1); 2610 __ IncrementCounter(&Counters::named_store_global_inline_miss, 1);
2601 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2611 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2602 __ jmp(ic, RelocInfo::CODE_TARGET); 2612 __ jmp(ic, RelocInfo::CODE_TARGET);
2603 2613
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
2693 // Handle store cache miss. 2703 // Handle store cache miss.
2694 __ bind(&miss); 2704 __ bind(&miss);
2695 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 2705 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
2696 __ jmp(ic, RelocInfo::CODE_TARGET); 2706 __ jmp(ic, RelocInfo::CODE_TARGET);
2697 2707
2698 // Return the generated code. 2708 // Return the generated code.
2699 return GetCode(NORMAL, NULL); 2709 return GetCode(NORMAL, NULL);
2700 } 2710 }
2701 2711
2702 2712
2713 MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
2714 JSObject* receiver) {
2715 // ----------- S t a t e -------------
2716 // -- eax : value
2717 // -- ecx : key
2718 // -- edx : receiver
2719 // -- esp[0] : return address
2720 // -----------------------------------
2721 Label miss;
2722
2723 // Check that the map matches.
2724 __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
2725
2726 // Do the load.
2727 GenerateFastPixelArrayStore(masm(),
2728 edx,
2729 ecx,
2730 eax,
2731 edi,
2732 ebx,
2733 true,
2734 &miss,
2735 &miss,
2736 NULL,
2737 &miss);
2738
2739 // Handle store cache miss.
2740 __ bind(&miss);
2741 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
2742 __ jmp(ic, RelocInfo::CODE_TARGET);
2743
2744 // Return the generated code.
2745 return GetCode(NORMAL, NULL);
2746 }
2747
2748
2703 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2749 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2704 JSObject* object, 2750 JSObject* object,
2705 JSObject* last) { 2751 JSObject* last) {
2706 // ----------- S t a t e ------------- 2752 // ----------- S t a t e -------------
2707 // -- eax : receiver 2753 // -- eax : receiver
2708 // -- ecx : name 2754 // -- ecx : name
2709 // -- esp[0] : return address 2755 // -- esp[0] : return address
2710 // ----------------------------------- 2756 // -----------------------------------
2711 Label miss; 2757 Label miss;
2712 2758
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2772 JSObject* object, 2818 JSObject* object,
2773 JSObject* holder, 2819 JSObject* holder,
2774 AccessorInfo* callback) { 2820 AccessorInfo* callback) {
2775 // ----------- S t a t e ------------- 2821 // ----------- S t a t e -------------
2776 // -- eax : receiver 2822 // -- eax : receiver
2777 // -- ecx : name 2823 // -- ecx : name
2778 // -- esp[0] : return address 2824 // -- esp[0] : return address
2779 // ----------------------------------- 2825 // -----------------------------------
2780 Label miss; 2826 Label miss;
2781 2827
2782 Failure* failure = Failure::InternalError(); 2828 MaybeObject* result = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx,
2783 bool success = GenerateLoadCallback(object, holder, eax, ecx, ebx, edx, edi, 2829 edi, callback, name, &miss);
2784 callback, name, &miss, &failure); 2830 if (result->IsFailure()) {
2785 if (!success) {
2786 miss.Unuse(); 2831 miss.Unuse();
2787 return failure; 2832 return result;
2788 } 2833 }
2789 2834
2790 __ bind(&miss); 2835 __ bind(&miss);
2791 GenerateLoadMiss(masm(), Code::LOAD_IC); 2836 GenerateLoadMiss(masm(), Code::LOAD_IC);
2792 2837
2793 // Return the generated code. 2838 // Return the generated code.
2794 return GetCode(CALLBACKS, name); 2839 return GetCode(CALLBACKS, name);
2795 } 2840 }
2796 2841
2797 2842
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
2941 // -- esp[0] : return address 2986 // -- esp[0] : return address
2942 // ----------------------------------- 2987 // -----------------------------------
2943 Label miss; 2988 Label miss;
2944 2989
2945 __ IncrementCounter(&Counters::keyed_load_callback, 1); 2990 __ IncrementCounter(&Counters::keyed_load_callback, 1);
2946 2991
2947 // Check that the name has not changed. 2992 // Check that the name has not changed.
2948 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 2993 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
2949 __ j(not_equal, &miss, not_taken); 2994 __ j(not_equal, &miss, not_taken);
2950 2995
2951 Failure* failure = Failure::InternalError(); 2996 MaybeObject* result = GenerateLoadCallback(receiver, holder, edx, eax, ebx,
2952 bool success = GenerateLoadCallback(receiver, holder, edx, eax, ebx, ecx, edi, 2997 ecx, edi, callback, name, &miss);
2953 callback, name, &miss, &failure); 2998 if (result->IsFailure()) {
2954 if (!success) {
2955 miss.Unuse(); 2999 miss.Unuse();
2956 return failure; 3000 return result;
2957 } 3001 }
2958 3002
2959 __ bind(&miss); 3003 __ bind(&miss);
2960 3004
2961 __ DecrementCounter(&Counters::keyed_load_callback, 1); 3005 __ DecrementCounter(&Counters::keyed_load_callback, 1);
2962 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3006 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2963 3007
2964 // Return the generated code. 3008 // Return the generated code.
2965 return GetCode(CALLBACKS, name); 3009 return GetCode(CALLBACKS, name);
2966 } 3010 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
3062 // -- esp[0] : return address 3106 // -- esp[0] : return address
3063 // ----------------------------------- 3107 // -----------------------------------
3064 Label miss; 3108 Label miss;
3065 3109
3066 __ IncrementCounter(&Counters::keyed_load_string_length, 1); 3110 __ IncrementCounter(&Counters::keyed_load_string_length, 1);
3067 3111
3068 // Check that the name has not changed. 3112 // Check that the name has not changed.
3069 __ cmp(Operand(eax), Immediate(Handle<String>(name))); 3113 __ cmp(Operand(eax), Immediate(Handle<String>(name)));
3070 __ j(not_equal, &miss, not_taken); 3114 __ j(not_equal, &miss, not_taken);
3071 3115
3072 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss); 3116 GenerateLoadStringLength(masm(), edx, ecx, ebx, &miss, true);
3073 __ bind(&miss); 3117 __ bind(&miss);
3074 __ DecrementCounter(&Counters::keyed_load_string_length, 1); 3118 __ DecrementCounter(&Counters::keyed_load_string_length, 1);
3075 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3119 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3076 3120
3077 // Return the generated code. 3121 // Return the generated code.
3078 return GetCode(CALLBACKS, name); 3122 return GetCode(CALLBACKS, name);
3079 } 3123 }
3080 3124
3081 3125
3082 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { 3126 MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
3141 __ ret(0); 3185 __ ret(0);
3142 3186
3143 __ bind(&miss); 3187 __ bind(&miss);
3144 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3188 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3145 3189
3146 // Return the generated code. 3190 // Return the generated code.
3147 return GetCode(NORMAL, NULL); 3191 return GetCode(NORMAL, NULL);
3148 } 3192 }
3149 3193
3150 3194
3195 MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
3196 // ----------- S t a t e -------------
3197 // -- eax : key
3198 // -- edx : receiver
3199 // -- esp[0] : return address
3200 // -----------------------------------
3201 Label miss;
3202
3203 // Check that the map matches.
3204 __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
3205
3206 GenerateFastPixelArrayLoad(masm(),
3207 edx,
3208 eax,
3209 ecx,
3210 ebx,
3211 eax,
3212 &miss,
3213 &miss,
3214 &miss);
3215
3216 // Handle load cache miss.
3217 __ bind(&miss);
3218 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss));
3219 __ jmp(ic, RelocInfo::CODE_TARGET);
3220
3221 // Return the generated code.
3222 return GetCode(NORMAL, NULL);
3223 }
3224
3225
3151 // Specialized stub for constructing objects from functions which only have only 3226 // Specialized stub for constructing objects from functions which only have only
3152 // simple assignments of the form this.x = ...; in their body. 3227 // simple assignments of the form this.x = ...; in their body.
3153 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3228 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3154 // ----------- S t a t e ------------- 3229 // ----------- S t a t e -------------
3155 // -- eax : argc 3230 // -- eax : argc
3156 // -- edi : constructor 3231 // -- edi : constructor
3157 // -- esp[0] : return address 3232 // -- esp[0] : return address
3158 // -- esp[4] : last argument 3233 // -- esp[4] : last argument
3159 // ----------------------------------- 3234 // -----------------------------------
3160 Label generic_stub_call; 3235 Label generic_stub_call;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
3279 __ bind(&generic_stub_call); 3354 __ bind(&generic_stub_call);
3280 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 3355 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
3281 Handle<Code> generic_construct_stub(code); 3356 Handle<Code> generic_construct_stub(code);
3282 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); 3357 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
3283 3358
3284 // Return the generated code. 3359 // Return the generated code.
3285 return GetCode(); 3360 return GetCode();
3286 } 3361 }
3287 3362
3288 3363
3364 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
3365 ExternalArrayType array_type, Code::Flags flags) {
3366 // ----------- S t a t e -------------
3367 // -- eax : key
3368 // -- edx : receiver
3369 // -- esp[0] : return address
3370 // -----------------------------------
3371 Label slow, failed_allocation;
3372
3373 // Check that the object isn't a smi.
3374 __ test(edx, Immediate(kSmiTagMask));
3375 __ j(zero, &slow, not_taken);
3376
3377 // Check that the key is a smi.
3378 __ test(eax, Immediate(kSmiTagMask));
3379 __ j(not_zero, &slow, not_taken);
3380
3381 // Get the map of the receiver.
3382 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset));
3383 // Check that the receiver does not require access checks. We need
3384 // to check this explicitly since this generic stub does not perform
3385 // map checks.
3386 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
3387 1 << Map::kIsAccessCheckNeeded);
3388 __ j(not_zero, &slow, not_taken);
3389
3390 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
3391 __ j(not_equal, &slow, not_taken);
3392
3393 // Check that the elements array is the appropriate type of
3394 // ExternalArray.
3395 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3396 Handle<Map> map(Heap::MapForExternalArrayType(array_type));
3397 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
3398 Immediate(map));
3399 __ j(not_equal, &slow, not_taken);
3400
3401 // eax: key, known to be a smi.
3402 // edx: receiver, known to be a JSObject.
3403 // ebx: elements object, known to be an external array.
3404 // Check that the index is in range.
3405 __ mov(ecx, eax);
3406 __ SmiUntag(ecx); // Untag the index.
3407 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
3408 // Unsigned comparison catches both negative and too-large values.
3409 __ j(above_equal, &slow);
3410
3411 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
3412 // ebx: base pointer of external storage
3413 switch (array_type) {
3414 case kExternalByteArray:
3415 __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0));
3416 break;
3417 case kExternalUnsignedByteArray:
3418 __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0));
3419 break;
3420 case kExternalShortArray:
3421 __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0));
3422 break;
3423 case kExternalUnsignedShortArray:
3424 __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0));
3425 break;
3426 case kExternalIntArray:
3427 case kExternalUnsignedIntArray:
3428 __ mov(ecx, Operand(ebx, ecx, times_4, 0));
3429 break;
3430 case kExternalFloatArray:
3431 __ fld_s(Operand(ebx, ecx, times_4, 0));
3432 break;
3433 default:
3434 UNREACHABLE();
3435 break;
3436 }
3437
3438 // For integer array types:
3439 // ecx: value
3440 // For floating-point array type:
3441 // FP(0): value
3442
3443 if (array_type == kExternalIntArray ||
3444 array_type == kExternalUnsignedIntArray) {
3445 // For the Int and UnsignedInt array types, we need to see whether
3446 // the value can be represented in a Smi. If not, we need to convert
3447 // it to a HeapNumber.
3448 Label box_int;
3449 if (array_type == kExternalIntArray) {
3450 __ cmp(ecx, 0xC0000000);
3451 __ j(sign, &box_int);
3452 } else {
3453 ASSERT_EQ(array_type, kExternalUnsignedIntArray);
3454 // The test is different for unsigned int values. Since we need
3455 // the value to be in the range of a positive smi, we can't
3456 // handle either of the top two bits being set in the value.
3457 __ test(ecx, Immediate(0xC0000000));
3458 __ j(not_zero, &box_int);
3459 }
3460
3461 __ mov(eax, ecx);
3462 __ SmiTag(eax);
3463 __ ret(0);
3464
3465 __ bind(&box_int);
3466
3467 // Allocate a HeapNumber for the int and perform int-to-double
3468 // conversion.
3469 if (array_type == kExternalIntArray) {
3470 __ push(ecx);
3471 __ fild_s(Operand(esp, 0));
3472 __ pop(ecx);
3473 } else {
3474 ASSERT(array_type == kExternalUnsignedIntArray);
3475 // Need to zero-extend the value.
3476 // There's no fild variant for unsigned values, so zero-extend
3477 // to a 64-bit int manually.
3478 __ push(Immediate(0));
3479 __ push(ecx);
3480 __ fild_d(Operand(esp, 0));
3481 __ pop(ecx);
3482 __ pop(ecx);
3483 }
3484 // FP(0): value
3485 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
3486 // Set the value.
3487 __ mov(eax, ecx);
3488 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
3489 __ ret(0);
3490 } else if (array_type == kExternalFloatArray) {
3491 // For the floating-point array type, we need to always allocate a
3492 // HeapNumber.
3493 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
3494 // Set the value.
3495 __ mov(eax, ecx);
3496 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
3497 __ ret(0);
3498 } else {
3499 __ mov(eax, ecx);
3500 __ SmiTag(eax);
3501 __ ret(0);
3502 }
3503
3504 // If we fail allocation of the HeapNumber, we still have a value on
3505 // top of the FPU stack. Remove it.
3506 __ bind(&failed_allocation);
3507 __ ffree();
3508 __ fincstp();
3509 // Fall through to slow case.
3510
3511 // Slow case: Jump to runtime.
3512 __ bind(&slow);
3513 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
3514 // ----------- S t a t e -------------
3515 // -- eax : key
3516 // -- edx : receiver
3517 // -- esp[0] : return address
3518 // -----------------------------------
3519
3520 __ pop(ebx);
3521 __ push(edx); // receiver
3522 __ push(eax); // name
3523 __ push(ebx); // return address
3524
3525 // Perform tail call to the entry.
3526 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3527
3528 // Return the generated code.
3529 return GetCode(flags);
3530 }
3531
3532
3533 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
3534 ExternalArrayType array_type, Code::Flags flags) {
3535 // ----------- S t a t e -------------
3536 // -- eax : value
3537 // -- ecx : key
3538 // -- edx : receiver
3539 // -- esp[0] : return address
3540 // -----------------------------------
3541 Label slow, check_heap_number;
3542
3543 // Check that the object isn't a smi.
3544 __ test(edx, Immediate(kSmiTagMask));
3545 __ j(zero, &slow);
3546 // Get the map from the receiver.
3547 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset));
3548 // Check that the receiver does not require access checks. We need
3549 // to do this because this generic stub does not perform map checks.
3550 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
3551 1 << Map::kIsAccessCheckNeeded);
3552 __ j(not_zero, &slow);
3553 // Check that the key is a smi.
3554 __ test(ecx, Immediate(kSmiTagMask));
3555 __ j(not_zero, &slow);
3556 // Get the instance type from the map of the receiver.
3557 __ CmpInstanceType(edi, JS_OBJECT_TYPE);
3558 __ j(not_equal, &slow);
3559
3560 // Check that the elements array is the appropriate type of
3561 // ExternalArray.
3562 // eax: value
3563 // edx: receiver, a JSObject
3564 // ecx: key, a smi
3565 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3566 __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)),
3567 &slow, true);
3568
3569 // Check that the index is in range.
3570 __ mov(ebx, ecx);
3571 __ SmiUntag(ebx);
3572 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
3573 // Unsigned comparison catches both negative and too-large values.
3574 __ j(above_equal, &slow);
3575
3576 // Handle both smis and HeapNumbers in the fast path. Go to the
3577 // runtime for all other kinds of values.
3578 // eax: value
3579 // edx: receiver
3580 // ecx: key
3581 // edi: elements array
3582 // ebx: untagged index
3583 __ test(eax, Immediate(kSmiTagMask));
3584 __ j(not_equal, &check_heap_number);
3585 // smi case
3586 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed.
3587 __ SmiUntag(ecx);
3588 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3589 // ecx: base pointer of external storage
3590 switch (array_type) {
3591 case kExternalByteArray:
3592 case kExternalUnsignedByteArray:
3593 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3594 break;
3595 case kExternalShortArray:
3596 case kExternalUnsignedShortArray:
3597 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
3598 break;
3599 case kExternalIntArray:
3600 case kExternalUnsignedIntArray:
3601 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3602 break;
3603 case kExternalFloatArray:
3604 // Need to perform int-to-float conversion.
3605 __ push(ecx);
3606 __ fild_s(Operand(esp, 0));
3607 __ pop(ecx);
3608 __ fstp_s(Operand(edi, ebx, times_4, 0));
3609 break;
3610 default:
3611 UNREACHABLE();
3612 break;
3613 }
3614 __ ret(0); // Return the original value.
3615
3616 __ bind(&check_heap_number);
3617 // eax: value
3618 // edx: receiver
3619 // ecx: key
3620 // edi: elements array
3621 // ebx: untagged index
3622 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3623 Immediate(Factory::heap_number_map()));
3624 __ j(not_equal, &slow);
3625
3626 // The WebGL specification leaves the behavior of storing NaN and
3627 // +/-Infinity into integer arrays basically undefined. For more
3628 // reproducible behavior, convert these to zero.
3629 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3630 // ebx: untagged index
3631 // edi: base pointer of external storage
3632 if (array_type == kExternalFloatArray) {
3633 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
3634 __ fstp_s(Operand(edi, ebx, times_4, 0));
3635 __ ret(0);
3636 } else {
3637 // Perform float-to-int conversion with truncation (round-to-zero)
3638 // behavior.
3639
3640 // For the moment we make the slow call to the runtime on
3641 // processors that don't support SSE2. The code in IntegerConvert
3642 // (code-stubs-ia32.cc) is roughly what is needed here though the
3643 // conversion failure case does not need to be handled.
3644 if (CpuFeatures::IsSupported(SSE2)) {
3645 if (array_type != kExternalIntArray &&
3646 array_type != kExternalUnsignedIntArray) {
3647 ASSERT(CpuFeatures::IsSupported(SSE2));
3648 CpuFeatures::Scope scope(SSE2);
3649 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
3650 // ecx: untagged integer value
3651 switch (array_type) {
3652 case kExternalByteArray:
3653 case kExternalUnsignedByteArray:
3654 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3655 break;
3656 case kExternalShortArray:
3657 case kExternalUnsignedShortArray:
3658 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
3659 break;
3660 default:
3661 UNREACHABLE();
3662 break;
3663 }
3664 } else {
3665 if (CpuFeatures::IsSupported(SSE3)) {
3666 CpuFeatures::Scope scope(SSE3);
3667 // fisttp stores values as signed integers. To represent the
3668 // entire range of int and unsigned int arrays, store as a
3669 // 64-bit int and discard the high 32 bits.
3670 // If the value is NaN or +/-infinity, the result is 0x80000000,
3671 // which is automatically zero when taken mod 2^n, n < 32.
3672 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
3673 __ sub(Operand(esp), Immediate(2 * kPointerSize));
3674 __ fisttp_d(Operand(esp, 0));
3675 __ pop(ecx);
3676 __ add(Operand(esp), Immediate(kPointerSize));
3677 } else {
3678 ASSERT(CpuFeatures::IsSupported(SSE2));
3679 CpuFeatures::Scope scope(SSE2);
3680 // We can easily implement the correct rounding behavior for the
3681 // range [0, 2^31-1]. For the time being, to keep this code simple,
3682 // make the slow runtime call for values outside this range.
3683 // Note: we could do better for signed int arrays.
3684 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
3685 // We will need the key if we have to make the slow runtime call.
3686 __ push(ecx);
3687 __ LoadPowerOf2(xmm1, ecx, 31);
3688 __ pop(ecx);
3689 __ ucomisd(xmm1, xmm0);
3690 __ j(above_equal, &slow);
3691 __ cvttsd2si(ecx, Operand(xmm0));
3692 }
3693 // ecx: untagged integer value
3694 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3695 }
3696 __ ret(0); // Return original value.
3697 }
3698 }
3699
3700 // Slow case: call runtime.
3701 __ bind(&slow);
3702 // ----------- S t a t e -------------
3703 // -- eax : value
3704 // -- ecx : key
3705 // -- edx : receiver
3706 // -- esp[0] : return address
3707 // -----------------------------------
3708
3709 __ pop(ebx);
3710 __ push(edx);
3711 __ push(ecx);
3712 __ push(eax);
3713 __ push(ebx);
3714
3715 // Do tail-call to runtime routine.
3716 __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
3717
3718 return GetCode(flags);
3719 }
3720
3721
3289 #undef __ 3722 #undef __
3290 3723
3291 } } // namespace v8::internal 3724 } } // namespace v8::internal
3292 3725
3293 #endif // V8_TARGET_ARCH_IA32 3726 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ia32/virtual-frame-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698