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

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

Issue 7348008: Merge up to 8597 to experimental/gc from the bleeding edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: '' Created 9 years, 5 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/regexp-macro-assembler-ia32.h ('k') | src/ic.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 122
123 const int kInterceptorOrAccessCheckNeededMask = 123 const int kInterceptorOrAccessCheckNeededMask =
124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 124 (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
125 125
126 // Bail out if the receiver has a named interceptor or requires access checks. 126 // Bail out if the receiver has a named interceptor or requires access checks.
127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset), 127 __ test_b(FieldOperand(r0, Map::kBitFieldOffset),
128 kInterceptorOrAccessCheckNeededMask); 128 kInterceptorOrAccessCheckNeededMask);
129 __ j(not_zero, miss_label); 129 __ j(not_zero, miss_label);
130 130
131 // Check that receiver is a JSObject. 131 // Check that receiver is a JSObject.
132 __ CmpInstanceType(r0, FIRST_JS_OBJECT_TYPE); 132 __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE);
133 __ j(below, miss_label); 133 __ j(below, miss_label);
134 134
135 // Load properties array. 135 // Load properties array.
136 Register properties = r0; 136 Register properties = r0;
137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 137 __ mov(properties, FieldOperand(receiver, JSObject::kPropertiesOffset));
138 138
139 // Check that the properties array is a dictionary. 139 // Check that the properties array is a dictionary.
140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset), 140 __ cmp(FieldOperand(properties, HeapObject::kMapOffset),
141 Immediate(masm->isolate()->factory()->hash_table_map())); 141 Immediate(masm->isolate()->factory()->hash_table_map()));
142 __ j(not_equal, miss_label); 142 __ j(not_equal, miss_label);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 ASSERT(!scratch.is(name)); 181 ASSERT(!scratch.is(name));
182 ASSERT(!extra.is(receiver)); 182 ASSERT(!extra.is(receiver));
183 ASSERT(!extra.is(name)); 183 ASSERT(!extra.is(name));
184 ASSERT(!extra.is(scratch)); 184 ASSERT(!extra.is(scratch));
185 185
186 // Check scratch and extra registers are valid, and extra2 is unused. 186 // Check scratch and extra registers are valid, and extra2 is unused.
187 ASSERT(!scratch.is(no_reg)); 187 ASSERT(!scratch.is(no_reg));
188 ASSERT(extra2.is(no_reg)); 188 ASSERT(extra2.is(no_reg));
189 189
190 // Check that the receiver isn't a smi. 190 // Check that the receiver isn't a smi.
191 __ test(receiver, Immediate(kSmiTagMask)); 191 __ JumpIfSmi(receiver, &miss);
192 __ j(zero, &miss);
193 192
194 // Get the map of the receiver and compute the hash. 193 // Get the map of the receiver and compute the hash.
195 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset)); 194 __ mov(scratch, FieldOperand(name, String::kHashFieldOffset));
196 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 195 __ add(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
197 __ xor_(scratch, flags); 196 __ xor_(scratch, flags);
198 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize); 197 __ and_(scratch, (kPrimaryTableSize - 1) << kHeapObjectTagSize);
199 198
200 // Probe the primary table. 199 // Probe the primary table.
201 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra); 200 ProbeTable(isolate, masm, flags, kPrimary, name, scratch, extra);
202 201
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 // Load the prototype from the initial map. 241 // Load the prototype from the initial map.
243 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 242 __ mov(prototype, FieldOperand(prototype, Map::kPrototypeOffset));
244 } 243 }
245 244
246 245
247 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 246 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
248 Register receiver, 247 Register receiver,
249 Register scratch, 248 Register scratch,
250 Label* miss_label) { 249 Label* miss_label) {
251 // Check that the receiver isn't a smi. 250 // Check that the receiver isn't a smi.
252 __ test(receiver, Immediate(kSmiTagMask)); 251 __ JumpIfSmi(receiver, miss_label);
253 __ j(zero, miss_label);
254 252
255 // Check that the object is a JS array. 253 // Check that the object is a JS array.
256 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 254 __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
257 __ j(not_equal, miss_label); 255 __ j(not_equal, miss_label);
258 256
259 // Load length directly from the JS array. 257 // Load length directly from the JS array.
260 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset)); 258 __ mov(eax, FieldOperand(receiver, JSArray::kLengthOffset));
261 __ ret(0); 259 __ ret(0);
262 } 260 }
263 261
264 262
265 // Generate code to check if an object is a string. If the object is 263 // Generate code to check if an object is a string. If the object is
266 // a string, the map's instance type is left in the scratch register. 264 // a string, the map's instance type is left in the scratch register.
267 static void GenerateStringCheck(MacroAssembler* masm, 265 static void GenerateStringCheck(MacroAssembler* masm,
268 Register receiver, 266 Register receiver,
269 Register scratch, 267 Register scratch,
270 Label* smi, 268 Label* smi,
271 Label* non_string_object) { 269 Label* non_string_object) {
272 // Check that the object isn't a smi. 270 // Check that the object isn't a smi.
273 __ test(receiver, Immediate(kSmiTagMask)); 271 __ JumpIfSmi(receiver, smi);
274 __ j(zero, smi);
275 272
276 // Check that the object is a string. 273 // Check that the object is a string.
277 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 274 __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
278 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 275 __ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
279 ASSERT(kNotStringTag != 0); 276 ASSERT(kNotStringTag != 0);
280 __ test(scratch, Immediate(kNotStringTag)); 277 __ test(scratch, Immediate(kNotStringTag));
281 __ j(not_zero, non_string_object); 278 __ j(not_zero, non_string_object);
282 } 279 }
283 280
284 281
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 Object* callback = optimization.api_call_info()->callback(); 452 Object* callback = optimization.api_call_info()->callback();
456 Address api_function_address = v8::ToCData<Address>(callback); 453 Address api_function_address = v8::ToCData<Address>(callback);
457 ApiFunction fun(api_function_address); 454 ApiFunction fun(api_function_address);
458 455
459 const int kApiArgc = 1; // API function gets reference to the v8::Arguments. 456 const int kApiArgc = 1; // API function gets reference to the v8::Arguments.
460 457
461 // Allocate the v8::Arguments structure in the arguments' space since 458 // Allocate the v8::Arguments structure in the arguments' space since
462 // it's not controlled by GC. 459 // it's not controlled by GC.
463 const int kApiStackSpace = 4; 460 const int kApiStackSpace = 4;
464 461
465 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace, ebx); 462 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace);
466 463
467 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_. 464 __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_.
468 __ add(Operand(eax), Immediate(argc * kPointerSize)); 465 __ add(Operand(eax), Immediate(argc * kPointerSize));
469 __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_. 466 __ mov(ApiParameterOperand(2), eax); // v8::Arguments::values_.
470 __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_. 467 __ Set(ApiParameterOperand(3), Immediate(argc)); // v8::Arguments::length_.
471 // v8::Arguments::is_construct_call_. 468 // v8::Arguments::is_construct_call_.
472 __ Set(ApiParameterOperand(4), Immediate(0)); 469 __ Set(ApiParameterOperand(4), Immediate(0));
473 470
474 // v8::InvocationCallback's argument. 471 // v8::InvocationCallback's argument.
475 __ lea(eax, ApiParameterOperand(1)); 472 __ lea(eax, ApiParameterOperand(1));
476 __ mov(ApiParameterOperand(0), eax); 473 __ mov(ApiParameterOperand(0), eax);
477 474
478 // Emitting a stub call may try to allocate (if the code is not 475 // Emitting a stub call may try to allocate (if the code is not
479 // already generated). Do not allow the assembler to perform a 476 // already generated). Do not allow the assembler to perform a
480 // garbage collection but instead return the allocation failure 477 // garbage collection but instead return the allocation failure
481 // object. 478 // object.
482 return masm->TryCallApiFunctionAndReturn(&fun, 479 return masm->TryCallApiFunctionAndReturn(&fun,
483 argc + kFastApiCallArguments + 1); 480 argc + kFastApiCallArguments + 1);
484 } 481 }
485 482
486 483
487 class CallInterceptorCompiler BASE_EMBEDDED { 484 class CallInterceptorCompiler BASE_EMBEDDED {
488 public: 485 public:
489 CallInterceptorCompiler(StubCompiler* stub_compiler, 486 CallInterceptorCompiler(StubCompiler* stub_compiler,
490 const ParameterCount& arguments, 487 const ParameterCount& arguments,
491 Register name) 488 Register name,
489 Code::ExtraICState extra_ic_state)
492 : stub_compiler_(stub_compiler), 490 : stub_compiler_(stub_compiler),
493 arguments_(arguments), 491 arguments_(arguments),
494 name_(name) {} 492 name_(name),
493 extra_ic_state_(extra_ic_state) {}
495 494
496 MaybeObject* Compile(MacroAssembler* masm, 495 MaybeObject* Compile(MacroAssembler* masm,
497 JSObject* object, 496 JSObject* object,
498 JSObject* holder, 497 JSObject* holder,
499 String* name, 498 String* name,
500 LookupResult* lookup, 499 LookupResult* lookup,
501 Register receiver, 500 Register receiver,
502 Register scratch1, 501 Register scratch1,
503 Register scratch2, 502 Register scratch2,
504 Register scratch3, 503 Register scratch3,
505 Label* miss) { 504 Label* miss) {
506 ASSERT(holder->HasNamedInterceptor()); 505 ASSERT(holder->HasNamedInterceptor());
507 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 506 ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
508 507
509 // Check that the receiver isn't a smi. 508 // Check that the receiver isn't a smi.
510 __ test(receiver, Immediate(kSmiTagMask)); 509 __ JumpIfSmi(receiver, miss);
511 __ j(zero, miss);
512 510
513 CallOptimization optimization(lookup); 511 CallOptimization optimization(lookup);
514 512
515 if (optimization.is_constant_call()) { 513 if (optimization.is_constant_call()) {
516 return CompileCacheable(masm, 514 return CompileCacheable(masm,
517 object, 515 object,
518 receiver, 516 receiver,
519 scratch1, 517 scratch1,
520 scratch2, 518 scratch2,
521 scratch3, 519 scratch3,
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 // by the previous CheckPrototypes. 607 // by the previous CheckPrototypes.
610 ASSERT(depth2 == kInvalidProtoDepth); 608 ASSERT(depth2 == kInvalidProtoDepth);
611 } 609 }
612 610
613 // Invoke function. 611 // Invoke function.
614 if (can_do_fast_api_call) { 612 if (can_do_fast_api_call) {
615 MaybeObject* result = 613 MaybeObject* result =
616 GenerateFastApiCall(masm, optimization, arguments_.immediate()); 614 GenerateFastApiCall(masm, optimization, arguments_.immediate());
617 if (result->IsFailure()) return result; 615 if (result->IsFailure()) return result;
618 } else { 616 } else {
617 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
618 ? CALL_AS_FUNCTION
619 : CALL_AS_METHOD;
619 __ InvokeFunction(optimization.constant_function(), arguments_, 620 __ InvokeFunction(optimization.constant_function(), arguments_,
620 JUMP_FUNCTION); 621 JUMP_FUNCTION, NullCallWrapper(), call_kind);
621 } 622 }
622 623
623 // Deferred code for fast API call case---clean preallocated space. 624 // Deferred code for fast API call case---clean preallocated space.
624 if (can_do_fast_api_call) { 625 if (can_do_fast_api_call) {
625 __ bind(&miss_cleanup); 626 __ bind(&miss_cleanup);
626 FreeSpaceForFastApiCall(masm, scratch1); 627 FreeSpaceForFastApiCall(masm, scratch1);
627 __ jmp(miss_label); 628 __ jmp(miss_label);
628 } 629 }
629 630
630 // Invoke a regular function. 631 // Invoke a regular function.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 __ pop(receiver); // Restore the holder. 690 __ pop(receiver); // Restore the holder.
690 __ LeaveInternalFrame(); 691 __ LeaveInternalFrame();
691 692
692 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel()); 693 __ cmp(eax, masm->isolate()->factory()->no_interceptor_result_sentinel());
693 __ j(not_equal, interceptor_succeeded); 694 __ j(not_equal, interceptor_succeeded);
694 } 695 }
695 696
696 StubCompiler* stub_compiler_; 697 StubCompiler* stub_compiler_;
697 const ParameterCount& arguments_; 698 const ParameterCount& arguments_;
698 Register name_; 699 Register name_;
700 Code::ExtraICState extra_ic_state_;
699 }; 701 };
700 702
701 703
702 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 704 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
703 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 705 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
704 Code* code = NULL; 706 Code* code = NULL;
705 if (kind == Code::LOAD_IC) { 707 if (kind == Code::LOAD_IC) {
706 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); 708 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
707 } else { 709 } else {
708 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); 710 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
(...skipping 16 matching lines...) Expand all
725 // but may be destroyed if store is successful. 727 // but may be destroyed if store is successful.
726 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 728 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
727 JSObject* object, 729 JSObject* object,
728 int index, 730 int index,
729 Map* transition, 731 Map* transition,
730 Register receiver_reg, 732 Register receiver_reg,
731 Register name_reg, 733 Register name_reg,
732 Register scratch, 734 Register scratch,
733 Label* miss_label) { 735 Label* miss_label) {
734 // Check that the object isn't a smi. 736 // Check that the object isn't a smi.
735 __ test(receiver_reg, Immediate(kSmiTagMask)); 737 __ JumpIfSmi(receiver_reg, miss_label);
736 __ j(zero, miss_label);
737 738
738 // Check that the map of the object hasn't changed. 739 // Check that the map of the object hasn't changed.
739 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset), 740 __ cmp(FieldOperand(receiver_reg, HeapObject::kMapOffset),
740 Immediate(Handle<Map>(object->map()))); 741 Immediate(Handle<Map>(object->map())));
741 __ j(not_equal, miss_label); 742 __ j(not_equal, miss_label);
742 743
743 // Perform global security token check if needed. 744 // Perform global security token check if needed.
744 if (object->IsJSGlobalProxy()) { 745 if (object->IsJSGlobalProxy()) {
745 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 746 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
746 } 747 }
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 void StubCompiler::GenerateLoadField(JSObject* object, 1016 void StubCompiler::GenerateLoadField(JSObject* object,
1016 JSObject* holder, 1017 JSObject* holder,
1017 Register receiver, 1018 Register receiver,
1018 Register scratch1, 1019 Register scratch1,
1019 Register scratch2, 1020 Register scratch2,
1020 Register scratch3, 1021 Register scratch3,
1021 int index, 1022 int index,
1022 String* name, 1023 String* name,
1023 Label* miss) { 1024 Label* miss) {
1024 // Check that the receiver isn't a smi. 1025 // Check that the receiver isn't a smi.
1025 __ test(receiver, Immediate(kSmiTagMask)); 1026 __ JumpIfSmi(receiver, miss);
1026 __ j(zero, miss);
1027 1027
1028 // Check the prototype chain. 1028 // Check the prototype chain.
1029 Register reg = 1029 Register reg =
1030 CheckPrototypes(object, receiver, holder, 1030 CheckPrototypes(object, receiver, holder,
1031 scratch1, scratch2, scratch3, name, miss); 1031 scratch1, scratch2, scratch3, name, miss);
1032 1032
1033 // Get the value from the properties. 1033 // Get the value from the properties.
1034 GenerateFastPropertyLoad(masm(), eax, reg, holder, index); 1034 GenerateFastPropertyLoad(masm(), eax, reg, holder, index);
1035 __ ret(0); 1035 __ ret(0);
1036 } 1036 }
1037 1037
1038 1038
1039 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, 1039 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
1040 JSObject* holder, 1040 JSObject* holder,
1041 Register receiver, 1041 Register receiver,
1042 Register name_reg, 1042 Register name_reg,
1043 Register scratch1, 1043 Register scratch1,
1044 Register scratch2, 1044 Register scratch2,
1045 Register scratch3, 1045 Register scratch3,
1046 AccessorInfo* callback, 1046 AccessorInfo* callback,
1047 String* name, 1047 String* name,
1048 Label* miss) { 1048 Label* miss) {
1049 // Check that the receiver isn't a smi. 1049 // Check that the receiver isn't a smi.
1050 __ test(receiver, Immediate(kSmiTagMask)); 1050 __ JumpIfSmi(receiver, miss);
1051 __ j(zero, miss);
1052 1051
1053 // Check that the maps haven't changed. 1052 // Check that the maps haven't changed.
1054 Register reg = 1053 Register reg =
1055 CheckPrototypes(object, receiver, holder, scratch1, 1054 CheckPrototypes(object, receiver, holder, scratch1,
1056 scratch2, scratch3, name, miss); 1055 scratch2, scratch3, name, miss);
1057 1056
1058 Handle<AccessorInfo> callback_handle(callback); 1057 Handle<AccessorInfo> callback_handle(callback);
1059 1058
1060 // Insert additional parameters into the stack frame above return address. 1059 // Insert additional parameters into the stack frame above return address.
1061 ASSERT(!scratch3.is(reg)); 1060 ASSERT(!scratch3.is(reg));
(...skipping 22 matching lines...) Expand all
1084 1083
1085 // Do call through the api. 1084 // Do call through the api.
1086 Address getter_address = v8::ToCData<Address>(callback->getter()); 1085 Address getter_address = v8::ToCData<Address>(callback->getter());
1087 ApiFunction fun(getter_address); 1086 ApiFunction fun(getter_address);
1088 1087
1089 // 3 elements array for v8::Agruments::values_, handler for name and pointer 1088 // 3 elements array for v8::Agruments::values_, handler for name and pointer
1090 // to the values (it considered as smi in GC). 1089 // to the values (it considered as smi in GC).
1091 const int kStackSpace = 5; 1090 const int kStackSpace = 5;
1092 const int kApiArgc = 2; 1091 const int kApiArgc = 2;
1093 1092
1094 __ PrepareCallApiFunction(kApiArgc, eax); 1093 __ PrepareCallApiFunction(kApiArgc);
1095 __ mov(ApiParameterOperand(0), ebx); // name. 1094 __ mov(ApiParameterOperand(0), ebx); // name.
1096 __ add(Operand(ebx), Immediate(kPointerSize)); 1095 __ add(Operand(ebx), Immediate(kPointerSize));
1097 __ mov(ApiParameterOperand(1), ebx); // arguments pointer. 1096 __ mov(ApiParameterOperand(1), ebx); // arguments pointer.
1098 1097
1099 // Emitting a stub call may try to allocate (if the code is not 1098 // Emitting a stub call may try to allocate (if the code is not
1100 // already generated). Do not allow the assembler to perform a 1099 // already generated). Do not allow the assembler to perform a
1101 // garbage collection but instead return the allocation failure 1100 // garbage collection but instead return the allocation failure
1102 // object. 1101 // object.
1103 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace); 1102 return masm()->TryCallApiFunctionAndReturn(&fun, kStackSpace);
1104 } 1103 }
1105 1104
1106 1105
1107 void StubCompiler::GenerateLoadConstant(JSObject* object, 1106 void StubCompiler::GenerateLoadConstant(JSObject* object,
1108 JSObject* holder, 1107 JSObject* holder,
1109 Register receiver, 1108 Register receiver,
1110 Register scratch1, 1109 Register scratch1,
1111 Register scratch2, 1110 Register scratch2,
1112 Register scratch3, 1111 Register scratch3,
1113 Object* value, 1112 Object* value,
1114 String* name, 1113 String* name,
1115 Label* miss) { 1114 Label* miss) {
1116 // Check that the receiver isn't a smi. 1115 // Check that the receiver isn't a smi.
1117 __ test(receiver, Immediate(kSmiTagMask)); 1116 __ JumpIfSmi(receiver, miss);
1118 __ j(zero, miss);
1119 1117
1120 // Check that the maps haven't changed. 1118 // Check that the maps haven't changed.
1121 CheckPrototypes(object, receiver, holder, 1119 CheckPrototypes(object, receiver, holder,
1122 scratch1, scratch2, scratch3, name, miss); 1120 scratch1, scratch2, scratch3, name, miss);
1123 1121
1124 // Return the constant value. 1122 // Return the constant value.
1125 __ mov(eax, Handle<Object>(value)); 1123 __ mov(eax, Handle<Object>(value));
1126 __ ret(0); 1124 __ ret(0);
1127 } 1125 }
1128 1126
1129 1127
1130 void StubCompiler::GenerateLoadInterceptor(JSObject* object, 1128 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
1131 JSObject* interceptor_holder, 1129 JSObject* interceptor_holder,
1132 LookupResult* lookup, 1130 LookupResult* lookup,
1133 Register receiver, 1131 Register receiver,
1134 Register name_reg, 1132 Register name_reg,
1135 Register scratch1, 1133 Register scratch1,
1136 Register scratch2, 1134 Register scratch2,
1137 Register scratch3, 1135 Register scratch3,
1138 String* name, 1136 String* name,
1139 Label* miss) { 1137 Label* miss) {
1140 ASSERT(interceptor_holder->HasNamedInterceptor()); 1138 ASSERT(interceptor_holder->HasNamedInterceptor());
1141 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1139 ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined());
1142 1140
1143 // Check that the receiver isn't a smi. 1141 // Check that the receiver isn't a smi.
1144 __ test(receiver, Immediate(kSmiTagMask)); 1142 __ JumpIfSmi(receiver, miss);
1145 __ j(zero, miss);
1146 1143
1147 // So far the most popular follow ups for interceptor loads are FIELD 1144 // So far the most popular follow ups for interceptor loads are FIELD
1148 // and CALLBACKS, so inline only them, other cases may be added 1145 // and CALLBACKS, so inline only them, other cases may be added
1149 // later. 1146 // later.
1150 bool compile_followup_inline = false; 1147 bool compile_followup_inline = false;
1151 if (lookup->IsProperty() && lookup->IsCacheable()) { 1148 if (lookup->IsProperty() && lookup->IsCacheable()) {
1152 if (lookup->type() == FIELD) { 1149 if (lookup->type() == FIELD) {
1153 compile_followup_inline = true; 1150 compile_followup_inline = true;
1154 } else if (lookup->type() == CALLBACKS && 1151 } else if (lookup->type() == CALLBACKS &&
1155 lookup->GetCallbackObject()->IsAccessorInfo() && 1152 lookup->GetCallbackObject()->IsAccessorInfo() &&
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 // Get the number of arguments. 1282 // Get the number of arguments.
1286 const int argc = arguments().immediate(); 1283 const int argc = arguments().immediate();
1287 1284
1288 // Get the receiver from the stack. 1285 // Get the receiver from the stack.
1289 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1286 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1290 1287
1291 // If the object is the holder then we know that it's a global 1288 // If the object is the holder then we know that it's a global
1292 // object which can only happen for contextual calls. In this case, 1289 // object which can only happen for contextual calls. In this case,
1293 // the receiver cannot be a smi. 1290 // the receiver cannot be a smi.
1294 if (object != holder) { 1291 if (object != holder) {
1295 __ test(edx, Immediate(kSmiTagMask)); 1292 __ JumpIfSmi(edx, miss);
1296 __ j(zero, miss);
1297 } 1293 }
1298 1294
1299 // Check that the maps haven't changed. 1295 // Check that the maps haven't changed.
1300 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss); 1296 CheckPrototypes(object, edx, holder, ebx, eax, edi, name, miss);
1301 } 1297 }
1302 1298
1303 1299
1304 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, 1300 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
1305 JSFunction* function, 1301 JSFunction* function,
1306 Label* miss) { 1302 Label* miss) {
1307 // Get the value from the cell. 1303 // Get the value from the cell.
1308 if (Serializer::enabled()) { 1304 if (Serializer::enabled()) {
1309 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell))); 1305 __ mov(edi, Immediate(Handle<JSGlobalPropertyCell>(cell)));
1310 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset)); 1306 __ mov(edi, FieldOperand(edi, JSGlobalPropertyCell::kValueOffset));
1311 } else { 1307 } else {
1312 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell))); 1308 __ mov(edi, Operand::Cell(Handle<JSGlobalPropertyCell>(cell)));
1313 } 1309 }
1314 1310
1315 // Check that the cell contains the same function. 1311 // Check that the cell contains the same function.
1316 if (isolate()->heap()->InNewSpace(function)) { 1312 if (isolate()->heap()->InNewSpace(function)) {
1317 // We can't embed a pointer to a function in new space so we have 1313 // We can't embed a pointer to a function in new space so we have
1318 // to verify that the shared function info is unchanged. This has 1314 // to verify that the shared function info is unchanged. This has
1319 // the nice side effect that multiple closures based on the same 1315 // the nice side effect that multiple closures based on the same
1320 // function can all use this call IC. Before we load through the 1316 // function can all use this call IC. Before we load through the
1321 // function, we have to verify that it still is a function. 1317 // function, we have to verify that it still is a function.
1322 __ test(edi, Immediate(kSmiTagMask)); 1318 __ JumpIfSmi(edi, miss);
1323 __ j(zero, miss);
1324 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1319 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1325 __ j(not_equal, miss); 1320 __ j(not_equal, miss);
1326 1321
1327 // Check the shared function info. Make sure it hasn't changed. 1322 // Check the shared function info. Make sure it hasn't changed.
1328 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset), 1323 __ cmp(FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset),
1329 Immediate(Handle<SharedFunctionInfo>(function->shared()))); 1324 Immediate(Handle<SharedFunctionInfo>(function->shared())));
1330 __ j(not_equal, miss); 1325 __ j(not_equal, miss);
1331 } else { 1326 } else {
1332 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function))); 1327 __ cmp(Operand(edi), Immediate(Handle<JSFunction>(function)));
1333 __ j(not_equal, miss); 1328 __ j(not_equal, miss);
(...skipping 27 matching lines...) Expand all
1361 // ----------------------------------- 1356 // -----------------------------------
1362 Label miss; 1357 Label miss;
1363 1358
1364 GenerateNameCheck(name, &miss); 1359 GenerateNameCheck(name, &miss);
1365 1360
1366 // Get the receiver from the stack. 1361 // Get the receiver from the stack.
1367 const int argc = arguments().immediate(); 1362 const int argc = arguments().immediate();
1368 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1363 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1369 1364
1370 // Check that the receiver isn't a smi. 1365 // Check that the receiver isn't a smi.
1371 __ test(edx, Immediate(kSmiTagMask)); 1366 __ JumpIfSmi(edx, &miss);
1372 __ j(zero, &miss);
1373 1367
1374 // Do the right check and compute the holder register. 1368 // Do the right check and compute the holder register.
1375 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi, 1369 Register reg = CheckPrototypes(object, edx, holder, ebx, eax, edi,
1376 name, &miss); 1370 name, &miss);
1377 1371
1378 GenerateFastPropertyLoad(masm(), edi, reg, holder, index); 1372 GenerateFastPropertyLoad(masm(), edi, reg, holder, index);
1379 1373
1380 // Check that the function really is a function. 1374 // Check that the function really is a function.
1381 __ test(edi, Immediate(kSmiTagMask)); 1375 __ JumpIfSmi(edi, &miss);
1382 __ j(zero, &miss);
1383 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx); 1376 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ebx);
1384 __ j(not_equal, &miss); 1377 __ j(not_equal, &miss);
1385 1378
1386 // Patch the receiver on the stack with the global proxy if 1379 // Patch the receiver on the stack with the global proxy if
1387 // necessary. 1380 // necessary.
1388 if (object->IsGlobalObject()) { 1381 if (object->IsGlobalObject()) {
1389 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 1382 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
1390 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 1383 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
1391 } 1384 }
1392 1385
1393 // Invoke the function. 1386 // Invoke the function.
1394 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); 1387 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
1388 ? CALL_AS_FUNCTION
1389 : CALL_AS_METHOD;
1390 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
1391 NullCallWrapper(), call_kind);
1395 1392
1396 // Handle call cache miss. 1393 // Handle call cache miss.
1397 __ bind(&miss); 1394 __ bind(&miss);
1398 MaybeObject* maybe_result = GenerateMissBranch(); 1395 MaybeObject* maybe_result = GenerateMissBranch();
1399 if (maybe_result->IsFailure()) return maybe_result; 1396 if (maybe_result->IsFailure()) return maybe_result;
1400 1397
1401 // Return the generated code. 1398 // Return the generated code.
1402 return GetCode(FIELD, name); 1399 return GetCode(FIELD, name);
1403 } 1400 }
1404 1401
(...skipping 18 matching lines...) Expand all
1423 1420
1424 Label miss; 1421 Label miss;
1425 1422
1426 GenerateNameCheck(name, &miss); 1423 GenerateNameCheck(name, &miss);
1427 1424
1428 // Get the receiver from the stack. 1425 // Get the receiver from the stack.
1429 const int argc = arguments().immediate(); 1426 const int argc = arguments().immediate();
1430 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1427 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1431 1428
1432 // Check that the receiver isn't a smi. 1429 // Check that the receiver isn't a smi.
1433 __ test(edx, Immediate(kSmiTagMask)); 1430 __ JumpIfSmi(edx, &miss);
1434 __ j(zero, &miss);
1435 1431
1436 CheckPrototypes(JSObject::cast(object), edx, 1432 CheckPrototypes(JSObject::cast(object), edx,
1437 holder, ebx, 1433 holder, ebx,
1438 eax, edi, name, &miss); 1434 eax, edi, name, &miss);
1439 1435
1440 if (argc == 0) { 1436 if (argc == 0) {
1441 // Noop, return the length. 1437 // Noop, return the length.
1442 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); 1438 __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset));
1443 __ ret((argc + 1) * kPointerSize); 1439 __ ret((argc + 1) * kPointerSize);
1444 } else { 1440 } else {
(...skipping 27 matching lines...) Expand all
1472 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); 1468 __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax);
1473 1469
1474 // Push the element. 1470 // Push the element.
1475 __ lea(edx, FieldOperand(ebx, 1471 __ lea(edx, FieldOperand(ebx,
1476 eax, times_half_pointer_size, 1472 eax, times_half_pointer_size,
1477 FixedArray::kHeaderSize - argc * kPointerSize)); 1473 FixedArray::kHeaderSize - argc * kPointerSize));
1478 __ mov(ecx, Operand(esp, argc * kPointerSize)); 1474 __ mov(ecx, Operand(esp, argc * kPointerSize));
1479 __ mov(Operand(edx, 0), ecx); 1475 __ mov(Operand(edx, 0), ecx);
1480 1476
1481 // Check if value is a smi. 1477 // Check if value is a smi.
1482 __ test(ecx, Immediate(kSmiTagMask)); 1478 __ JumpIfNotSmi(ecx, &with_write_barrier);
1483 __ j(not_zero, &with_write_barrier, Label::kNear);
1484 1479
1485 __ bind(&exit); 1480 __ bind(&exit);
1486 __ ret((argc + 1) * kPointerSize); 1481 __ ret((argc + 1) * kPointerSize);
1487 1482
1488 __ bind(&with_write_barrier); 1483 __ bind(&with_write_barrier);
1489 1484
1490 __ RecordWrite( 1485 __ RecordWrite(
1491 ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 1486 ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
1492 1487
1493 __ ret((argc + 1) * kPointerSize); 1488 __ ret((argc + 1) * kPointerSize);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1591 1586
1592 Label miss, return_undefined, call_builtin; 1587 Label miss, return_undefined, call_builtin;
1593 1588
1594 GenerateNameCheck(name, &miss); 1589 GenerateNameCheck(name, &miss);
1595 1590
1596 // Get the receiver from the stack. 1591 // Get the receiver from the stack.
1597 const int argc = arguments().immediate(); 1592 const int argc = arguments().immediate();
1598 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 1593 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
1599 1594
1600 // Check that the receiver isn't a smi. 1595 // Check that the receiver isn't a smi.
1601 __ test(edx, Immediate(kSmiTagMask)); 1596 __ JumpIfSmi(edx, &miss);
1602 __ j(zero, &miss);
1603 CheckPrototypes(JSObject::cast(object), edx, 1597 CheckPrototypes(JSObject::cast(object), edx,
1604 holder, ebx, 1598 holder, ebx,
1605 eax, edi, name, &miss); 1599 eax, edi, name, &miss);
1606 1600
1607 // Get the elements array of the object. 1601 // Get the elements array of the object.
1608 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset)); 1602 __ mov(ebx, FieldOperand(edx, JSArray::kElementsOffset));
1609 1603
1610 // Check that the elements are in fast mode and writable. 1604 // Check that the elements are in fast mode and writable.
1611 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset), 1605 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
1612 Immediate(factory()->fixed_array_map())); 1606 Immediate(factory()->fixed_array_map()));
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1851 return isolate()->heap()->undefined_value(); 1845 return isolate()->heap()->undefined_value();
1852 } 1846 }
1853 1847
1854 Label miss; 1848 Label miss;
1855 GenerateNameCheck(name, &miss); 1849 GenerateNameCheck(name, &miss);
1856 1850
1857 if (cell == NULL) { 1851 if (cell == NULL) {
1858 __ mov(edx, Operand(esp, 2 * kPointerSize)); 1852 __ mov(edx, Operand(esp, 2 * kPointerSize));
1859 1853
1860 STATIC_ASSERT(kSmiTag == 0); 1854 STATIC_ASSERT(kSmiTag == 0);
1861 __ test(edx, Immediate(kSmiTagMask)); 1855 __ JumpIfSmi(edx, &miss);
1862 __ j(zero, &miss);
1863 1856
1864 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, 1857 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name,
1865 &miss); 1858 &miss);
1866 } else { 1859 } else {
1867 ASSERT(cell->value() == function); 1860 ASSERT(cell->value() == function);
1868 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 1861 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
1869 GenerateLoadFunctionFromCell(cell, function, &miss); 1862 GenerateLoadFunctionFromCell(cell, function, &miss);
1870 } 1863 }
1871 1864
1872 // Load the char code argument. 1865 // Load the char code argument.
1873 Register code = ebx; 1866 Register code = ebx;
1874 __ mov(code, Operand(esp, 1 * kPointerSize)); 1867 __ mov(code, Operand(esp, 1 * kPointerSize));
1875 1868
1876 // Check the code is a smi. 1869 // Check the code is a smi.
1877 Label slow; 1870 Label slow;
1878 STATIC_ASSERT(kSmiTag == 0); 1871 STATIC_ASSERT(kSmiTag == 0);
1879 __ test(code, Immediate(kSmiTagMask)); 1872 __ JumpIfNotSmi(code, &slow);
1880 __ j(not_zero, &slow);
1881 1873
1882 // Convert the smi code to uint16. 1874 // Convert the smi code to uint16.
1883 __ and_(code, Immediate(Smi::FromInt(0xffff))); 1875 __ and_(code, Immediate(Smi::FromInt(0xffff)));
1884 1876
1885 StringCharFromCodeGenerator char_from_code_generator(code, eax); 1877 StringCharFromCodeGenerator char_from_code_generator(code, eax);
1886 char_from_code_generator.GenerateFast(masm()); 1878 char_from_code_generator.GenerateFast(masm());
1887 __ ret(2 * kPointerSize); 1879 __ ret(2 * kPointerSize);
1888 1880
1889 StubRuntimeCallHelper call_helper; 1881 StubRuntimeCallHelper call_helper;
1890 char_from_code_generator.GenerateSlow(masm(), call_helper); 1882 char_from_code_generator.GenerateSlow(masm(), call_helper);
1891 1883
1892 // Tail call the full function. We do not have to patch the receiver 1884 // Tail call the full function. We do not have to patch the receiver
1893 // because the function makes no use of it. 1885 // because the function makes no use of it.
1894 __ bind(&slow); 1886 __ bind(&slow);
1895 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 1887 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
1888 ? CALL_AS_FUNCTION
1889 : CALL_AS_METHOD;
1890 __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
1891 NullCallWrapper(), call_kind);
1896 1892
1897 __ bind(&miss); 1893 __ bind(&miss);
1898 // ecx: function name. 1894 // ecx: function name.
1899 MaybeObject* maybe_result = GenerateMissBranch(); 1895 MaybeObject* maybe_result = GenerateMissBranch();
1900 if (maybe_result->IsFailure()) return maybe_result; 1896 if (maybe_result->IsFailure()) return maybe_result;
1901 1897
1902 // Return the generated code. 1898 // Return the generated code.
1903 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 1899 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
1904 } 1900 }
1905 1901
(...skipping 25 matching lines...) Expand all
1931 return isolate()->heap()->undefined_value(); 1927 return isolate()->heap()->undefined_value();
1932 } 1928 }
1933 1929
1934 Label miss; 1930 Label miss;
1935 GenerateNameCheck(name, &miss); 1931 GenerateNameCheck(name, &miss);
1936 1932
1937 if (cell == NULL) { 1933 if (cell == NULL) {
1938 __ mov(edx, Operand(esp, 2 * kPointerSize)); 1934 __ mov(edx, Operand(esp, 2 * kPointerSize));
1939 1935
1940 STATIC_ASSERT(kSmiTag == 0); 1936 STATIC_ASSERT(kSmiTag == 0);
1941 __ test(edx, Immediate(kSmiTagMask)); 1937 __ JumpIfSmi(edx, &miss);
1942 __ j(zero, &miss);
1943 1938
1944 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, 1939 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name,
1945 &miss); 1940 &miss);
1946 } else { 1941 } else {
1947 ASSERT(cell->value() == function); 1942 ASSERT(cell->value() == function);
1948 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 1943 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
1949 GenerateLoadFunctionFromCell(cell, function, &miss); 1944 GenerateLoadFunctionFromCell(cell, function, &miss);
1950 } 1945 }
1951 1946
1952 // Load the (only) argument into eax. 1947 // Load the (only) argument into eax.
1953 __ mov(eax, Operand(esp, 1 * kPointerSize)); 1948 __ mov(eax, Operand(esp, 1 * kPointerSize));
1954 1949
1955 // Check if the argument is a smi. 1950 // Check if the argument is a smi.
1956 Label smi; 1951 Label smi;
1957 STATIC_ASSERT(kSmiTag == 0); 1952 STATIC_ASSERT(kSmiTag == 0);
1958 __ test(eax, Immediate(kSmiTagMask)); 1953 __ JumpIfSmi(eax, &smi);
1959 __ j(zero, &smi);
1960 1954
1961 // Check if the argument is a heap number and load its value into xmm0. 1955 // Check if the argument is a heap number and load its value into xmm0.
1962 Label slow; 1956 Label slow;
1963 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 1957 __ CheckMap(eax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK);
1964 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 1958 __ movdbl(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
1965 1959
1966 // Check if the argument is strictly positive. Note this also 1960 // Check if the argument is strictly positive. Note this also
1967 // discards NaN. 1961 // discards NaN.
1968 __ xorpd(xmm1, xmm1); 1962 __ xorpd(xmm1, xmm1);
1969 __ ucomisd(xmm0, xmm1); 1963 __ ucomisd(xmm0, xmm1);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
2015 __ ret(2 * kPointerSize); 2009 __ ret(2 * kPointerSize);
2016 2010
2017 // Return the argument (when it's an already round heap number). 2011 // Return the argument (when it's an already round heap number).
2018 __ bind(&already_round); 2012 __ bind(&already_round);
2019 __ mov(eax, Operand(esp, 1 * kPointerSize)); 2013 __ mov(eax, Operand(esp, 1 * kPointerSize));
2020 __ ret(2 * kPointerSize); 2014 __ ret(2 * kPointerSize);
2021 2015
2022 // Tail call the full function. We do not have to patch the receiver 2016 // Tail call the full function. We do not have to patch the receiver
2023 // because the function makes no use of it. 2017 // because the function makes no use of it.
2024 __ bind(&slow); 2018 __ bind(&slow);
2025 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2019 __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2020 NullCallWrapper(), CALL_AS_METHOD);
2026 2021
2027 __ bind(&miss); 2022 __ bind(&miss);
2028 // ecx: function name. 2023 // ecx: function name.
2029 MaybeObject* maybe_result = GenerateMissBranch(); 2024 MaybeObject* maybe_result = GenerateMissBranch();
2030 if (maybe_result->IsFailure()) return maybe_result; 2025 if (maybe_result->IsFailure()) return maybe_result;
2031 2026
2032 // Return the generated code. 2027 // Return the generated code.
2033 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 2028 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
2034 } 2029 }
2035 2030
(...skipping 19 matching lines...) Expand all
2055 return isolate()->heap()->undefined_value(); 2050 return isolate()->heap()->undefined_value();
2056 } 2051 }
2057 2052
2058 Label miss; 2053 Label miss;
2059 GenerateNameCheck(name, &miss); 2054 GenerateNameCheck(name, &miss);
2060 2055
2061 if (cell == NULL) { 2056 if (cell == NULL) {
2062 __ mov(edx, Operand(esp, 2 * kPointerSize)); 2057 __ mov(edx, Operand(esp, 2 * kPointerSize));
2063 2058
2064 STATIC_ASSERT(kSmiTag == 0); 2059 STATIC_ASSERT(kSmiTag == 0);
2065 __ test(edx, Immediate(kSmiTagMask)); 2060 __ JumpIfSmi(edx, &miss);
2066 __ j(zero, &miss);
2067 2061
2068 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name, 2062 CheckPrototypes(JSObject::cast(object), edx, holder, ebx, eax, edi, name,
2069 &miss); 2063 &miss);
2070 } else { 2064 } else {
2071 ASSERT(cell->value() == function); 2065 ASSERT(cell->value() == function);
2072 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 2066 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
2073 GenerateLoadFunctionFromCell(cell, function, &miss); 2067 GenerateLoadFunctionFromCell(cell, function, &miss);
2074 } 2068 }
2075 2069
2076 // Load the (only) argument into eax. 2070 // Load the (only) argument into eax.
2077 __ mov(eax, Operand(esp, 1 * kPointerSize)); 2071 __ mov(eax, Operand(esp, 1 * kPointerSize));
2078 2072
2079 // Check if the argument is a smi. 2073 // Check if the argument is a smi.
2080 Label not_smi; 2074 Label not_smi;
2081 STATIC_ASSERT(kSmiTag == 0); 2075 STATIC_ASSERT(kSmiTag == 0);
2082 __ test(eax, Immediate(kSmiTagMask)); 2076 __ JumpIfNotSmi(eax, &not_smi);
2083 __ j(not_zero, &not_smi);
2084 2077
2085 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 2078 // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0
2086 // otherwise. 2079 // otherwise.
2087 __ mov(ebx, eax); 2080 __ mov(ebx, eax);
2088 __ sar(ebx, kBitsPerInt - 1); 2081 __ sar(ebx, kBitsPerInt - 1);
2089 2082
2090 // Do bitwise not or do nothing depending on ebx. 2083 // Do bitwise not or do nothing depending on ebx.
2091 __ xor_(eax, Operand(ebx)); 2084 __ xor_(eax, Operand(ebx));
2092 2085
2093 // Add 1 or do nothing depending on ebx. 2086 // Add 1 or do nothing depending on ebx.
(...skipping 26 matching lines...) Expand all
2120 __ and_(ebx, ~HeapNumber::kSignMask); 2113 __ and_(ebx, ~HeapNumber::kSignMask);
2121 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset)); 2114 __ mov(ecx, FieldOperand(eax, HeapNumber::kMantissaOffset));
2122 __ AllocateHeapNumber(eax, edi, edx, &slow); 2115 __ AllocateHeapNumber(eax, edi, edx, &slow);
2123 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx); 2116 __ mov(FieldOperand(eax, HeapNumber::kExponentOffset), ebx);
2124 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx); 2117 __ mov(FieldOperand(eax, HeapNumber::kMantissaOffset), ecx);
2125 __ ret(2 * kPointerSize); 2118 __ ret(2 * kPointerSize);
2126 2119
2127 // Tail call the full function. We do not have to patch the receiver 2120 // Tail call the full function. We do not have to patch the receiver
2128 // because the function makes no use of it. 2121 // because the function makes no use of it.
2129 __ bind(&slow); 2122 __ bind(&slow);
2130 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2123 __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2124 NullCallWrapper(), CALL_AS_METHOD);
2131 2125
2132 __ bind(&miss); 2126 __ bind(&miss);
2133 // ecx: function name. 2127 // ecx: function name.
2134 MaybeObject* maybe_result = GenerateMissBranch(); 2128 MaybeObject* maybe_result = GenerateMissBranch();
2135 if (maybe_result->IsFailure()) return maybe_result; 2129 if (maybe_result->IsFailure()) return maybe_result;
2136 2130
2137 // Return the generated code. 2131 // Return the generated code.
2138 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 2132 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
2139 } 2133 }
2140 2134
(...skipping 17 matching lines...) Expand all
2158 2152
2159 Label miss, miss_before_stack_reserved; 2153 Label miss, miss_before_stack_reserved;
2160 2154
2161 GenerateNameCheck(name, &miss_before_stack_reserved); 2155 GenerateNameCheck(name, &miss_before_stack_reserved);
2162 2156
2163 // Get the receiver from the stack. 2157 // Get the receiver from the stack.
2164 const int argc = arguments().immediate(); 2158 const int argc = arguments().immediate();
2165 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2159 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2166 2160
2167 // Check that the receiver isn't a smi. 2161 // Check that the receiver isn't a smi.
2168 __ test(edx, Immediate(kSmiTagMask)); 2162 __ JumpIfSmi(edx, &miss_before_stack_reserved);
2169 __ j(zero, &miss_before_stack_reserved);
2170 2163
2171 Counters* counters = isolate()->counters(); 2164 Counters* counters = isolate()->counters();
2172 __ IncrementCounter(counters->call_const(), 1); 2165 __ IncrementCounter(counters->call_const(), 1);
2173 __ IncrementCounter(counters->call_const_fast_api(), 1); 2166 __ IncrementCounter(counters->call_const_fast_api(), 1);
2174 2167
2175 // Allocate space for v8::Arguments implicit values. Must be initialized 2168 // Allocate space for v8::Arguments implicit values. Must be initialized
2176 // before calling any runtime function. 2169 // before calling any runtime function.
2177 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize)); 2170 __ sub(Operand(esp), Immediate(kFastApiCallArguments * kPointerSize));
2178 2171
2179 // Check that the maps haven't changed and find a Holder as a side effect. 2172 // Check that the maps haven't changed and find a Holder as a side effect.
(...skipping 14 matching lines...) Expand all
2194 2187
2195 __ bind(&miss_before_stack_reserved); 2188 __ bind(&miss_before_stack_reserved);
2196 MaybeObject* maybe_result = GenerateMissBranch(); 2189 MaybeObject* maybe_result = GenerateMissBranch();
2197 if (maybe_result->IsFailure()) return maybe_result; 2190 if (maybe_result->IsFailure()) return maybe_result;
2198 2191
2199 // Return the generated code. 2192 // Return the generated code.
2200 return GetCode(function); 2193 return GetCode(function);
2201 } 2194 }
2202 2195
2203 2196
2204 MaybeObject* CallStubCompiler::CompileCallConstant(Object* object, 2197 MaybeObject* CallStubCompiler::CompileCallConstant(
2205 JSObject* holder, 2198 Object* object,
2206 JSFunction* function, 2199 JSObject* holder,
2207 String* name, 2200 JSFunction* function,
2208 CheckType check) { 2201 String* name,
2202 CheckType check) {
2209 // ----------- S t a t e ------------- 2203 // ----------- S t a t e -------------
2210 // -- ecx : name 2204 // -- ecx : name
2211 // -- esp[0] : return address 2205 // -- esp[0] : return address
2212 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2206 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2213 // -- ... 2207 // -- ...
2214 // -- esp[(argc + 1) * 4] : receiver 2208 // -- esp[(argc + 1) * 4] : receiver
2215 // ----------------------------------- 2209 // -----------------------------------
2216 2210
2217 if (HasCustomCallGenerator(function)) { 2211 if (HasCustomCallGenerator(function)) {
2218 MaybeObject* maybe_result = CompileCustomCall( 2212 MaybeObject* maybe_result = CompileCustomCall(
2219 object, holder, NULL, function, name); 2213 object, holder, NULL, function, name);
2220 Object* result; 2214 Object* result;
2221 if (!maybe_result->ToObject(&result)) return maybe_result; 2215 if (!maybe_result->ToObject(&result)) return maybe_result;
2222 // undefined means bail out to regular compiler. 2216 // undefined means bail out to regular compiler.
2223 if (!result->IsUndefined()) return result; 2217 if (!result->IsUndefined()) return result;
2224 } 2218 }
2225 2219
2226 Label miss; 2220 Label miss;
2227 2221
2228 GenerateNameCheck(name, &miss); 2222 GenerateNameCheck(name, &miss);
2229 2223
2230 // Get the receiver from the stack. 2224 // Get the receiver from the stack.
2231 const int argc = arguments().immediate(); 2225 const int argc = arguments().immediate();
2232 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2226 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2233 2227
2234 // Check that the receiver isn't a smi. 2228 // Check that the receiver isn't a smi.
2235 if (check != NUMBER_CHECK) { 2229 if (check != NUMBER_CHECK) {
2236 __ test(edx, Immediate(kSmiTagMask)); 2230 __ JumpIfSmi(edx, &miss);
2237 __ j(zero, &miss);
2238 } 2231 }
2239 2232
2240 // Make sure that it's okay not to patch the on stack receiver 2233 // Make sure that it's okay not to patch the on stack receiver
2241 // unless we're doing a receiver map check. 2234 // unless we're doing a receiver map check.
2242 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2235 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2243 2236
2244 SharedFunctionInfo* function_info = function->shared(); 2237 SharedFunctionInfo* function_info = function->shared();
2245 switch (check) { 2238 switch (check) {
2246 case RECEIVER_MAP_CHECK: 2239 case RECEIVER_MAP_CHECK:
2247 __ IncrementCounter(isolate()->counters()->call_const(), 1); 2240 __ IncrementCounter(isolate()->counters()->call_const(), 1);
(...skipping 28 matching lines...) Expand all
2276 break; 2269 break;
2277 2270
2278 case NUMBER_CHECK: { 2271 case NUMBER_CHECK: {
2279 if (!function->IsBuiltin() && !function_info->strict_mode()) { 2272 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2280 // Calling non-strict non-builtins with a value as the receiver 2273 // Calling non-strict non-builtins with a value as the receiver
2281 // requires boxing. 2274 // requires boxing.
2282 __ jmp(&miss); 2275 __ jmp(&miss);
2283 } else { 2276 } else {
2284 Label fast; 2277 Label fast;
2285 // Check that the object is a smi or a heap number. 2278 // Check that the object is a smi or a heap number.
2286 __ test(edx, Immediate(kSmiTagMask)); 2279 __ JumpIfSmi(edx, &fast);
2287 __ j(zero, &fast);
2288 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); 2280 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
2289 __ j(not_equal, &miss); 2281 __ j(not_equal, &miss);
2290 __ bind(&fast); 2282 __ bind(&fast);
2291 // Check that the maps starting from the prototype haven't changed. 2283 // Check that the maps starting from the prototype haven't changed.
2292 GenerateDirectLoadGlobalFunctionPrototype( 2284 GenerateDirectLoadGlobalFunctionPrototype(
2293 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); 2285 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
2294 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 2286 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
2295 ebx, edx, edi, name, &miss); 2287 ebx, edx, edi, name, &miss);
2296 } 2288 }
2297 break; 2289 break;
(...skipping 18 matching lines...) Expand all
2316 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 2308 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
2317 ebx, edx, edi, name, &miss); 2309 ebx, edx, edi, name, &miss);
2318 } 2310 }
2319 break; 2311 break;
2320 } 2312 }
2321 2313
2322 default: 2314 default:
2323 UNREACHABLE(); 2315 UNREACHABLE();
2324 } 2316 }
2325 2317
2326 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2318 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
2319 ? CALL_AS_FUNCTION
2320 : CALL_AS_METHOD;
2321 __ InvokeFunction(function, arguments(), JUMP_FUNCTION,
2322 NullCallWrapper(), call_kind);
2327 2323
2328 // Handle call cache miss. 2324 // Handle call cache miss.
2329 __ bind(&miss); 2325 __ bind(&miss);
2330 MaybeObject* maybe_result = GenerateMissBranch(); 2326 MaybeObject* maybe_result = GenerateMissBranch();
2331 if (maybe_result->IsFailure()) return maybe_result; 2327 if (maybe_result->IsFailure()) return maybe_result;
2332 2328
2333 // Return the generated code. 2329 // Return the generated code.
2334 return GetCode(function); 2330 return GetCode(function);
2335 } 2331 }
2336 2332
(...skipping 14 matching lines...) Expand all
2351 2347
2352 // Get the number of arguments. 2348 // Get the number of arguments.
2353 const int argc = arguments().immediate(); 2349 const int argc = arguments().immediate();
2354 2350
2355 LookupResult lookup; 2351 LookupResult lookup;
2356 LookupPostInterceptor(holder, name, &lookup); 2352 LookupPostInterceptor(holder, name, &lookup);
2357 2353
2358 // Get the receiver from the stack. 2354 // Get the receiver from the stack.
2359 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2355 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2360 2356
2361 CallInterceptorCompiler compiler(this, arguments(), ecx); 2357 CallInterceptorCompiler compiler(this, arguments(), ecx, extra_ic_state_);
2362 MaybeObject* result = compiler.Compile(masm(), 2358 MaybeObject* result = compiler.Compile(masm(),
2363 object, 2359 object,
2364 holder, 2360 holder,
2365 name, 2361 name,
2366 &lookup, 2362 &lookup,
2367 edx, 2363 edx,
2368 ebx, 2364 ebx,
2369 edi, 2365 edi,
2370 eax, 2366 eax,
2371 &miss); 2367 &miss);
2372 if (result->IsFailure()) return result; 2368 if (result->IsFailure()) return result;
2373 2369
2374 // Restore receiver. 2370 // Restore receiver.
2375 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); 2371 __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
2376 2372
2377 // Check that the function really is a function. 2373 // Check that the function really is a function.
2378 __ test(eax, Immediate(kSmiTagMask)); 2374 __ JumpIfSmi(eax, &miss);
2379 __ j(zero, &miss);
2380 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx); 2375 __ CmpObjectType(eax, JS_FUNCTION_TYPE, ebx);
2381 __ j(not_equal, &miss); 2376 __ j(not_equal, &miss);
2382 2377
2383 // Patch the receiver on the stack with the global proxy if 2378 // Patch the receiver on the stack with the global proxy if
2384 // necessary. 2379 // necessary.
2385 if (object->IsGlobalObject()) { 2380 if (object->IsGlobalObject()) {
2386 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2381 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2387 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2382 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2388 } 2383 }
2389 2384
2390 // Invoke the function. 2385 // Invoke the function.
2391 __ mov(edi, eax); 2386 __ mov(edi, eax);
2392 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION); 2387 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
2388 ? CALL_AS_FUNCTION
2389 : CALL_AS_METHOD;
2390 __ InvokeFunction(edi, arguments(), JUMP_FUNCTION,
2391 NullCallWrapper(), call_kind);
2393 2392
2394 // Handle load cache miss. 2393 // Handle load cache miss.
2395 __ bind(&miss); 2394 __ bind(&miss);
2396 MaybeObject* maybe_result = GenerateMissBranch(); 2395 MaybeObject* maybe_result = GenerateMissBranch();
2397 if (maybe_result->IsFailure()) return maybe_result; 2396 if (maybe_result->IsFailure()) return maybe_result;
2398 2397
2399 // Return the generated code. 2398 // Return the generated code.
2400 return GetCode(INTERCEPTOR, name); 2399 return GetCode(INTERCEPTOR, name);
2401 } 2400 }
2402 2401
2403 2402
2404 MaybeObject* CallStubCompiler::CompileCallGlobal( 2403 MaybeObject* CallStubCompiler::CompileCallGlobal(
2405 JSObject* object, 2404 JSObject* object,
2406 GlobalObject* holder, 2405 GlobalObject* holder,
2407 JSGlobalPropertyCell* cell, 2406 JSGlobalPropertyCell* cell,
2408 JSFunction* function, 2407 JSFunction* function,
2409 String* name, 2408 String* name) {
2410 Code::ExtraICState extra_ic_state) {
2411 // ----------- S t a t e ------------- 2409 // ----------- S t a t e -------------
2412 // -- ecx : name 2410 // -- ecx : name
2413 // -- esp[0] : return address 2411 // -- esp[0] : return address
2414 // -- esp[(argc - n) * 4] : arg[n] (zero-based) 2412 // -- esp[(argc - n) * 4] : arg[n] (zero-based)
2415 // -- ... 2413 // -- ...
2416 // -- esp[(argc + 1) * 4] : receiver 2414 // -- esp[(argc + 1) * 4] : receiver
2417 // ----------------------------------- 2415 // -----------------------------------
2418 2416
2419 if (HasCustomCallGenerator(function)) { 2417 if (HasCustomCallGenerator(function)) {
2420 MaybeObject* maybe_result = CompileCustomCall( 2418 MaybeObject* maybe_result = CompileCustomCall(
(...skipping 22 matching lines...) Expand all
2443 } 2441 }
2444 2442
2445 // Setup the context (function already in edi). 2443 // Setup the context (function already in edi).
2446 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); 2444 __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
2447 2445
2448 // Jump to the cached code (tail call). 2446 // Jump to the cached code (tail call).
2449 Counters* counters = isolate()->counters(); 2447 Counters* counters = isolate()->counters();
2450 __ IncrementCounter(counters->call_global_inline(), 1); 2448 __ IncrementCounter(counters->call_global_inline(), 1);
2451 ASSERT(function->is_compiled()); 2449 ASSERT(function->is_compiled());
2452 ParameterCount expected(function->shared()->formal_parameter_count()); 2450 ParameterCount expected(function->shared()->formal_parameter_count());
2453 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) 2451 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
2454 ? CALL_AS_FUNCTION 2452 ? CALL_AS_FUNCTION
2455 : CALL_AS_METHOD; 2453 : CALL_AS_METHOD;
2456 if (V8::UseCrankshaft()) { 2454 if (V8::UseCrankshaft()) {
2457 // TODO(kasperl): For now, we always call indirectly through the 2455 // TODO(kasperl): For now, we always call indirectly through the
2458 // code field in the function to allow recompilation to take effect 2456 // code field in the function to allow recompilation to take effect
2459 // without changing any of the call sites. 2457 // without changing any of the call sites.
2460 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), 2458 __ InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
2461 expected, arguments(), JUMP_FUNCTION, 2459 expected, arguments(), JUMP_FUNCTION,
2462 NullCallWrapper(), call_kind); 2460 NullCallWrapper(), call_kind);
2463 } else { 2461 } else {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2514 String* name) { 2512 String* name) {
2515 // ----------- S t a t e ------------- 2513 // ----------- S t a t e -------------
2516 // -- eax : value 2514 // -- eax : value
2517 // -- ecx : name 2515 // -- ecx : name
2518 // -- edx : receiver 2516 // -- edx : receiver
2519 // -- esp[0] : return address 2517 // -- esp[0] : return address
2520 // ----------------------------------- 2518 // -----------------------------------
2521 Label miss; 2519 Label miss;
2522 2520
2523 // Check that the object isn't a smi. 2521 // Check that the object isn't a smi.
2524 __ test(edx, Immediate(kSmiTagMask)); 2522 __ JumpIfSmi(edx, &miss);
2525 __ j(zero, &miss);
2526 2523
2527 // Check that the map of the object hasn't changed. 2524 // Check that the map of the object hasn't changed.
2528 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2525 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2529 Immediate(Handle<Map>(object->map()))); 2526 Immediate(Handle<Map>(object->map())));
2530 __ j(not_equal, &miss); 2527 __ j(not_equal, &miss);
2531 2528
2532 // Perform global security token check if needed. 2529 // Perform global security token check if needed.
2533 if (object->IsJSGlobalProxy()) { 2530 if (object->IsJSGlobalProxy()) {
2534 __ CheckAccessGlobalProxy(edx, ebx, &miss); 2531 __ CheckAccessGlobalProxy(edx, ebx, &miss);
2535 } 2532 }
(...skipping 28 matching lines...) Expand all
2564 String* name) { 2561 String* name) {
2565 // ----------- S t a t e ------------- 2562 // ----------- S t a t e -------------
2566 // -- eax : value 2563 // -- eax : value
2567 // -- ecx : name 2564 // -- ecx : name
2568 // -- edx : receiver 2565 // -- edx : receiver
2569 // -- esp[0] : return address 2566 // -- esp[0] : return address
2570 // ----------------------------------- 2567 // -----------------------------------
2571 Label miss; 2568 Label miss;
2572 2569
2573 // Check that the object isn't a smi. 2570 // Check that the object isn't a smi.
2574 __ test(edx, Immediate(kSmiTagMask)); 2571 __ JumpIfSmi(edx, &miss);
2575 __ j(zero, &miss);
2576 2572
2577 // Check that the map of the object hasn't changed. 2573 // Check that the map of the object hasn't changed.
2578 __ cmp(FieldOperand(edx, HeapObject::kMapOffset), 2574 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2579 Immediate(Handle<Map>(receiver->map()))); 2575 Immediate(Handle<Map>(receiver->map())));
2580 __ j(not_equal, &miss); 2576 __ j(not_equal, &miss);
2581 2577
2582 // Perform global security token check if needed. 2578 // Perform global security token check if needed.
2583 if (receiver->IsJSGlobalProxy()) { 2579 if (receiver->IsJSGlobalProxy()) {
2584 __ CheckAccessGlobalProxy(edx, ebx, &miss); 2580 __ CheckAccessGlobalProxy(edx, ebx, &miss);
2585 } 2581 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
2702 __ bind(&miss); 2698 __ bind(&miss);
2703 __ DecrementCounter(counters->keyed_store_field(), 1); 2699 __ DecrementCounter(counters->keyed_store_field(), 1);
2704 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2700 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2705 __ jmp(ic, RelocInfo::CODE_TARGET); 2701 __ jmp(ic, RelocInfo::CODE_TARGET);
2706 2702
2707 // Return the generated code. 2703 // Return the generated code.
2708 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2704 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2709 } 2705 }
2710 2706
2711 2707
2712 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement( 2708 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) {
2713 Map* receiver_map) {
2714 // ----------- S t a t e ------------- 2709 // ----------- S t a t e -------------
2715 // -- eax : value 2710 // -- eax : value
2716 // -- ecx : key 2711 // -- ecx : key
2717 // -- edx : receiver 2712 // -- edx : receiver
2718 // -- esp[0] : return address 2713 // -- esp[0] : return address
2719 // ----------------------------------- 2714 // -----------------------------------
2720 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 2715 Code* stub;
2716 JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
2717 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
2721 MaybeObject* maybe_stub = 2718 MaybeObject* maybe_stub =
2722 KeyedStoreFastElementStub(is_js_array).TryGetCode(); 2719 KeyedStoreElementStub(is_jsarray, elements_kind).TryGetCode();
2723 Code* stub;
2724 if (!maybe_stub->To(&stub)) return maybe_stub; 2720 if (!maybe_stub->To(&stub)) return maybe_stub;
2725 __ DispatchMap(edx, 2721 __ DispatchMap(edx,
2726 Handle<Map>(receiver_map), 2722 Handle<Map>(receiver_map),
2727 Handle<Code>(stub), 2723 Handle<Code>(stub),
2728 DO_SMI_CHECK); 2724 DO_SMI_CHECK);
2729 2725
2730 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2726 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2731 __ jmp(ic, RelocInfo::CODE_TARGET); 2727 __ jmp(ic, RelocInfo::CODE_TARGET);
2732 2728
2733 // Return the generated code. 2729 // Return the generated code.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2768 JSObject* object, 2764 JSObject* object,
2769 JSObject* last) { 2765 JSObject* last) {
2770 // ----------- S t a t e ------------- 2766 // ----------- S t a t e -------------
2771 // -- eax : receiver 2767 // -- eax : receiver
2772 // -- ecx : name 2768 // -- ecx : name
2773 // -- esp[0] : return address 2769 // -- esp[0] : return address
2774 // ----------------------------------- 2770 // -----------------------------------
2775 Label miss; 2771 Label miss;
2776 2772
2777 // Check that the receiver isn't a smi. 2773 // Check that the receiver isn't a smi.
2778 __ test(eax, Immediate(kSmiTagMask)); 2774 __ JumpIfSmi(eax, &miss);
2779 __ j(zero, &miss);
2780 2775
2781 ASSERT(last->IsGlobalObject() || last->HasFastProperties()); 2776 ASSERT(last->IsGlobalObject() || last->HasFastProperties());
2782 2777
2783 // Check the maps of the full prototype chain. Also check that 2778 // Check the maps of the full prototype chain. Also check that
2784 // global property cells up to (but not including) the last object 2779 // global property cells up to (but not including) the last object
2785 // in the prototype chain are empty. 2780 // in the prototype chain are empty.
2786 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss); 2781 CheckPrototypes(object, eax, last, ebx, edx, edi, name, &miss);
2787 2782
2788 // If the last object in the prototype chain is a global object, 2783 // If the last object in the prototype chain is a global object,
2789 // check that the global property cell is empty. 2784 // check that the global property cell is empty.
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
2921 // -- eax : receiver 2916 // -- eax : receiver
2922 // -- ecx : name 2917 // -- ecx : name
2923 // -- esp[0] : return address 2918 // -- esp[0] : return address
2924 // ----------------------------------- 2919 // -----------------------------------
2925 Label miss; 2920 Label miss;
2926 2921
2927 // If the object is the holder then we know that it's a global 2922 // If the object is the holder then we know that it's a global
2928 // object which can only happen for contextual loads. In this case, 2923 // object which can only happen for contextual loads. In this case,
2929 // the receiver cannot be a smi. 2924 // the receiver cannot be a smi.
2930 if (object != holder) { 2925 if (object != holder) {
2931 __ test(eax, Immediate(kSmiTagMask)); 2926 __ JumpIfSmi(eax, &miss);
2932 __ j(zero, &miss);
2933 } 2927 }
2934 2928
2935 // Check that the maps haven't changed. 2929 // Check that the maps haven't changed.
2936 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss); 2930 CheckPrototypes(object, eax, holder, ebx, edx, edi, name, &miss);
2937 2931
2938 // Get the value from the cell. 2932 // Get the value from the cell.
2939 if (Serializer::enabled()) { 2933 if (Serializer::enabled()) {
2940 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell))); 2934 __ mov(ebx, Immediate(Handle<JSGlobalPropertyCell>(cell)));
2941 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset)); 2935 __ mov(ebx, FieldOperand(ebx, JSGlobalPropertyCell::kValueOffset));
2942 } else { 2936 } else {
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
3166 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); 3160 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
3167 __ bind(&miss); 3161 __ bind(&miss);
3168 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 3162 __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
3169 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3163 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3170 3164
3171 // Return the generated code. 3165 // Return the generated code.
3172 return GetCode(CALLBACKS, name); 3166 return GetCode(CALLBACKS, name);
3173 } 3167 }
3174 3168
3175 3169
3176 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) { 3170 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) {
3177 // ----------- S t a t e ------------- 3171 // ----------- S t a t e -------------
3178 // -- eax : key 3172 // -- eax : key
3179 // -- edx : receiver 3173 // -- edx : receiver
3180 // -- esp[0] : return address 3174 // -- esp[0] : return address
3181 // ----------------------------------- 3175 // -----------------------------------
3182 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
3183 Code* stub; 3176 Code* stub;
3177 JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
3178 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode();
3184 if (!maybe_stub->To(&stub)) return maybe_stub; 3179 if (!maybe_stub->To(&stub)) return maybe_stub;
3185 __ DispatchMap(edx, 3180 __ DispatchMap(edx,
3186 Handle<Map>(receiver_map), 3181 Handle<Map>(receiver_map),
3187 Handle<Code>(stub), 3182 Handle<Code>(stub),
3188 DO_SMI_CHECK); 3183 DO_SMI_CHECK);
3189 3184
3190 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3185 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3191 3186
3192 // Return the generated code. 3187 // Return the generated code.
3193 return GetCode(NORMAL, NULL); 3188 return GetCode(NORMAL, NULL);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3238 // code for the function thereby hitting the break points. 3233 // code for the function thereby hitting the break points.
3239 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); 3234 __ mov(ebx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
3240 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset)); 3235 __ mov(ebx, FieldOperand(ebx, SharedFunctionInfo::kDebugInfoOffset));
3241 __ cmp(ebx, factory()->undefined_value()); 3236 __ cmp(ebx, factory()->undefined_value());
3242 __ j(not_equal, &generic_stub_call); 3237 __ j(not_equal, &generic_stub_call);
3243 #endif 3238 #endif
3244 3239
3245 // Load the initial map and verify that it is in fact a map. 3240 // Load the initial map and verify that it is in fact a map.
3246 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset)); 3241 __ mov(ebx, FieldOperand(edi, JSFunction::kPrototypeOrInitialMapOffset));
3247 // Will both indicate a NULL and a Smi. 3242 // Will both indicate a NULL and a Smi.
3248 __ test(ebx, Immediate(kSmiTagMask)); 3243 __ JumpIfSmi(ebx, &generic_stub_call);
3249 __ j(zero, &generic_stub_call);
3250 __ CmpObjectType(ebx, MAP_TYPE, ecx); 3244 __ CmpObjectType(ebx, MAP_TYPE, ecx);
3251 __ j(not_equal, &generic_stub_call); 3245 __ j(not_equal, &generic_stub_call);
3252 3246
3253 #ifdef DEBUG 3247 #ifdef DEBUG
3254 // Cannot construct functions this way. 3248 // Cannot construct functions this way.
3255 // edi: constructor 3249 // edi: constructor
3256 // ebx: initial map 3250 // ebx: initial map
3257 __ CmpInstanceType(ebx, JS_FUNCTION_TYPE); 3251 __ CmpInstanceType(ebx, JS_FUNCTION_TYPE);
3258 __ Assert(not_equal, "Function constructed by construct stub."); 3252 __ Assert(not_equal, "Function constructed by construct stub.");
3259 #endif 3253 #endif
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
3354 __ bind(&generic_stub_call); 3348 __ bind(&generic_stub_call);
3355 Handle<Code> generic_construct_stub = 3349 Handle<Code> generic_construct_stub =
3356 isolate()->builtins()->JSConstructStubGeneric(); 3350 isolate()->builtins()->JSConstructStubGeneric();
3357 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); 3351 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
3358 3352
3359 // Return the generated code. 3353 // Return the generated code.
3360 return GetCode(); 3354 return GetCode();
3361 } 3355 }
3362 3356
3363 3357
3364 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3365 JSObject*receiver, ExternalArrayType array_type) {
3366 // ----------- S t a t e -------------
3367 // -- eax : key
3368 // -- edx : receiver
3369 // -- esp[0] : return address
3370 // -----------------------------------
3371 MaybeObject* maybe_stub =
3372 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3373 Code* stub;
3374 if (!maybe_stub->To(&stub)) return maybe_stub;
3375 __ DispatchMap(edx,
3376 Handle<Map>(receiver->map()),
3377 Handle<Code>(stub),
3378 DO_SMI_CHECK);
3379
3380 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3381 __ jmp(ic, RelocInfo::CODE_TARGET);
3382
3383 // Return the generated code.
3384 return GetCode();
3385 }
3386
3387
3388 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3389 JSObject* receiver, ExternalArrayType array_type) {
3390 // ----------- S t a t e -------------
3391 // -- eax : value
3392 // -- ecx : key
3393 // -- edx : receiver
3394 // -- esp[0] : return address
3395 // -----------------------------------
3396 MaybeObject* maybe_stub =
3397 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3398 Code* stub;
3399 if (!maybe_stub->To(&stub)) return maybe_stub;
3400 __ DispatchMap(edx,
3401 Handle<Map>(receiver->map()),
3402 Handle<Code>(stub),
3403 DO_SMI_CHECK);
3404
3405 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3406 __ jmp(ic, RelocInfo::CODE_TARGET);
3407
3408 return GetCode();
3409 }
3410
3411
3412 #undef __ 3358 #undef __
3413 #define __ ACCESS_MASM(masm) 3359 #define __ ACCESS_MASM(masm)
3414 3360
3415 3361
3416 void KeyedLoadStubCompiler::GenerateLoadExternalArray( 3362 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
3417 MacroAssembler* masm, 3363 MacroAssembler* masm) {
3418 ExternalArrayType array_type) {
3419 // ----------- S t a t e ------------- 3364 // ----------- S t a t e -------------
3420 // -- eax : key 3365 // -- eax : key
3421 // -- edx : receiver 3366 // -- edx : receiver
3367 // -- esp[0] : return address
3368 // -----------------------------------
3369 Label slow, miss_force_generic;
3370
3371 // This stub is meant to be tail-jumped to, the receiver must already
3372 // have been verified by the caller to not be a smi.
3373 __ JumpIfNotSmi(eax, &miss_force_generic);
3374 __ mov(ebx, eax);
3375 __ SmiUntag(ebx);
3376 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3377
3378 // Push receiver on the stack to free up a register for the dictionary
3379 // probing.
3380 __ push(edx);
3381 __ LoadFromNumberDictionary(&slow,
3382 ecx,
3383 eax,
3384 ebx,
3385 edx,
3386 edi,
3387 eax);
3388 // Pop receiver before returning.
3389 __ pop(edx);
3390 __ ret(0);
3391
3392 __ bind(&slow);
3393 __ pop(edx);
3394
3395 // ----------- S t a t e -------------
3396 // -- eax : value
3397 // -- ecx : key
3398 // -- edx : receiver
3399 // -- esp[0] : return address
3400 // -----------------------------------
3401
3402 Handle<Code> slow_ic =
3403 masm->isolate()->builtins()->KeyedLoadIC_Slow();
3404 __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3405
3406 __ bind(&miss_force_generic);
3407 // ----------- S t a t e -------------
3408 // -- eax : value
3409 // -- ecx : key
3410 // -- edx : receiver
3411 // -- esp[0] : return address
3412 // -----------------------------------
3413
3414 Handle<Code> miss_force_generic_ic =
3415 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3416 __ jmp(miss_force_generic_ic, RelocInfo::CODE_TARGET);
3417 }
3418
3419
3420 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3421 MacroAssembler* masm,
3422 JSObject::ElementsKind elements_kind) {
3423 // ----------- S t a t e -------------
3424 // -- eax : key
3425 // -- edx : receiver
3422 // -- esp[0] : return address 3426 // -- esp[0] : return address
3423 // ----------------------------------- 3427 // -----------------------------------
3424 Label miss_force_generic, failed_allocation, slow; 3428 Label miss_force_generic, failed_allocation, slow;
3425 3429
3426 // This stub is meant to be tail-jumped to, the receiver must already 3430 // This stub is meant to be tail-jumped to, the receiver must already
3427 // have been verified by the caller to not be a smi. 3431 // have been verified by the caller to not be a smi.
3428 3432
3429 // Check that the key is a smi. 3433 // Check that the key is a smi.
3430 __ test(eax, Immediate(kSmiTagMask)); 3434 __ JumpIfNotSmi(eax, &miss_force_generic);
3431 __ j(not_zero, &miss_force_generic);
3432 3435
3433 // Check that the index is in range. 3436 // Check that the index is in range.
3434 __ mov(ecx, eax); 3437 __ mov(ecx, eax);
3435 __ SmiUntag(ecx); // Untag the index. 3438 __ SmiUntag(ecx); // Untag the index.
3436 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 3439 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3437 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 3440 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
3438 // Unsigned comparison catches both negative and too-large values. 3441 // Unsigned comparison catches both negative and too-large values.
3439 __ j(above_equal, &miss_force_generic); 3442 __ j(above_equal, &miss_force_generic);
3440 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 3443 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
3441 // ebx: base pointer of external storage 3444 // ebx: base pointer of external storage
3442 switch (array_type) { 3445 switch (elements_kind) {
3443 case kExternalByteArray: 3446 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3444 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); 3447 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
3445 break; 3448 break;
3446 case kExternalUnsignedByteArray: 3449 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3447 case kExternalPixelArray: 3450 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3448 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); 3451 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
3449 break; 3452 break;
3450 case kExternalShortArray: 3453 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3451 __ movsx_w(eax, Operand(ebx, ecx, times_2, 0)); 3454 __ movsx_w(eax, Operand(ebx, ecx, times_2, 0));
3452 break; 3455 break;
3453 case kExternalUnsignedShortArray: 3456 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3454 __ movzx_w(eax, Operand(ebx, ecx, times_2, 0)); 3457 __ movzx_w(eax, Operand(ebx, ecx, times_2, 0));
3455 break; 3458 break;
3456 case kExternalIntArray: 3459 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3457 case kExternalUnsignedIntArray: 3460 case JSObject::EXTERNAL_INT_ELEMENTS:
3458 __ mov(ecx, Operand(ebx, ecx, times_4, 0)); 3461 __ mov(ecx, Operand(ebx, ecx, times_4, 0));
3459 break; 3462 break;
3460 case kExternalFloatArray: 3463 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3461 __ fld_s(Operand(ebx, ecx, times_4, 0)); 3464 __ fld_s(Operand(ebx, ecx, times_4, 0));
3462 break; 3465 break;
3463 case kExternalDoubleArray: 3466 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3464 __ fld_d(Operand(ebx, ecx, times_8, 0)); 3467 __ fld_d(Operand(ebx, ecx, times_8, 0));
3465 break; 3468 break;
3466 default: 3469 default:
3467 UNREACHABLE(); 3470 UNREACHABLE();
3468 break; 3471 break;
3469 } 3472 }
3470 3473
3471 // For integer array types: 3474 // For integer array types:
3472 // ecx: value 3475 // ecx: value
3473 // For floating-point array type: 3476 // For floating-point array type:
3474 // FP(0): value 3477 // FP(0): value
3475 3478
3476 if (array_type == kExternalIntArray || 3479 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS ||
3477 array_type == kExternalUnsignedIntArray) { 3480 elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) {
3478 // For the Int and UnsignedInt array types, we need to see whether 3481 // For the Int and UnsignedInt array types, we need to see whether
3479 // the value can be represented in a Smi. If not, we need to convert 3482 // the value can be represented in a Smi. If not, we need to convert
3480 // it to a HeapNumber. 3483 // it to a HeapNumber.
3481 Label box_int; 3484 Label box_int;
3482 if (array_type == kExternalIntArray) { 3485 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) {
3483 __ cmp(ecx, 0xC0000000); 3486 __ cmp(ecx, 0xC0000000);
3484 __ j(sign, &box_int); 3487 __ j(sign, &box_int);
3485 } else { 3488 } else {
3486 ASSERT_EQ(array_type, kExternalUnsignedIntArray); 3489 ASSERT_EQ(JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
3487 // The test is different for unsigned int values. Since we need 3490 // The test is different for unsigned int values. Since we need
3488 // the value to be in the range of a positive smi, we can't 3491 // the value to be in the range of a positive smi, we can't
3489 // handle either of the top two bits being set in the value. 3492 // handle either of the top two bits being set in the value.
3490 __ test(ecx, Immediate(0xC0000000)); 3493 __ test(ecx, Immediate(0xC0000000));
3491 __ j(not_zero, &box_int); 3494 __ j(not_zero, &box_int);
3492 } 3495 }
3493 3496
3494 __ mov(eax, ecx); 3497 __ mov(eax, ecx);
3495 __ SmiTag(eax); 3498 __ SmiTag(eax);
3496 __ ret(0); 3499 __ ret(0);
3497 3500
3498 __ bind(&box_int); 3501 __ bind(&box_int);
3499 3502
3500 // Allocate a HeapNumber for the int and perform int-to-double 3503 // Allocate a HeapNumber for the int and perform int-to-double
3501 // conversion. 3504 // conversion.
3502 if (array_type == kExternalIntArray) { 3505 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) {
3503 __ push(ecx); 3506 __ push(ecx);
3504 __ fild_s(Operand(esp, 0)); 3507 __ fild_s(Operand(esp, 0));
3505 __ pop(ecx); 3508 __ pop(ecx);
3506 } else { 3509 } else {
3507 ASSERT(array_type == kExternalUnsignedIntArray); 3510 ASSERT_EQ(JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS, elements_kind);
3508 // Need to zero-extend the value. 3511 // Need to zero-extend the value.
3509 // There's no fild variant for unsigned values, so zero-extend 3512 // There's no fild variant for unsigned values, so zero-extend
3510 // to a 64-bit int manually. 3513 // to a 64-bit int manually.
3511 __ push(Immediate(0)); 3514 __ push(Immediate(0));
3512 __ push(ecx); 3515 __ push(ecx);
3513 __ fild_d(Operand(esp, 0)); 3516 __ fild_d(Operand(esp, 0));
3514 __ pop(ecx); 3517 __ pop(ecx);
3515 __ pop(ecx); 3518 __ pop(ecx);
3516 } 3519 }
3517 // FP(0): value 3520 // FP(0): value
3518 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 3521 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
3519 // Set the value. 3522 // Set the value.
3520 __ mov(eax, ecx); 3523 __ mov(eax, ecx);
3521 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3524 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
3522 __ ret(0); 3525 __ ret(0);
3523 } else if (array_type == kExternalFloatArray || 3526 } else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS ||
3524 array_type == kExternalDoubleArray) { 3527 elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
3525 // For the floating-point array type, we need to always allocate a 3528 // For the floating-point array type, we need to always allocate a
3526 // HeapNumber. 3529 // HeapNumber.
3527 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 3530 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
3528 // Set the value. 3531 // Set the value.
3529 __ mov(eax, ecx); 3532 __ mov(eax, ecx);
3530 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3533 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
3531 __ ret(0); 3534 __ ret(0);
3532 } else { 3535 } else {
3533 __ SmiTag(eax); 3536 __ SmiTag(eax);
3534 __ ret(0); 3537 __ ret(0);
(...skipping 29 matching lines...) Expand all
3564 // Miss case: Jump to runtime. 3567 // Miss case: Jump to runtime.
3565 __ bind(&miss_force_generic); 3568 __ bind(&miss_force_generic);
3566 Handle<Code> miss_ic = 3569 Handle<Code> miss_ic =
3567 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3570 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3568 __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3571 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3569 } 3572 }
3570 3573
3571 3574
3572 void KeyedStoreStubCompiler::GenerateStoreExternalArray( 3575 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3573 MacroAssembler* masm, 3576 MacroAssembler* masm,
3574 ExternalArrayType array_type) { 3577 JSObject::ElementsKind elements_kind) {
3575 // ----------- S t a t e ------------- 3578 // ----------- S t a t e -------------
3576 // -- eax : key 3579 // -- eax : key
3577 // -- edx : receiver 3580 // -- edx : receiver
3578 // -- esp[0] : return address 3581 // -- esp[0] : return address
3579 // ----------------------------------- 3582 // -----------------------------------
3580 Label miss_force_generic, slow, check_heap_number; 3583 Label miss_force_generic, slow, check_heap_number;
3581 3584
3582 // This stub is meant to be tail-jumped to, the receiver must already 3585 // This stub is meant to be tail-jumped to, the receiver must already
3583 // have been verified by the caller to not be a smi. 3586 // have been verified by the caller to not be a smi.
3584 3587
3585 // Check that the key is a smi. 3588 // Check that the key is a smi.
3586 __ test(ecx, Immediate(kSmiTagMask)); 3589 __ JumpIfNotSmi(ecx, &miss_force_generic);
3587 __ j(not_zero, &miss_force_generic);
3588 3590
3589 // Check that the index is in range. 3591 // Check that the index is in range.
3590 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3592 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3591 __ mov(ebx, ecx); 3593 __ mov(ebx, ecx);
3592 __ SmiUntag(ebx); 3594 __ SmiUntag(ebx);
3593 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); 3595 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
3594 // Unsigned comparison catches both negative and too-large values. 3596 // Unsigned comparison catches both negative and too-large values.
3595 __ j(above_equal, &slow); 3597 __ j(above_equal, &slow);
3596 3598
3597 // Handle both smis and HeapNumbers in the fast path. Go to the 3599 // Handle both smis and HeapNumbers in the fast path. Go to the
3598 // runtime for all other kinds of values. 3600 // runtime for all other kinds of values.
3599 // eax: value 3601 // eax: value
3600 // edx: receiver 3602 // edx: receiver
3601 // ecx: key 3603 // ecx: key
3602 // edi: elements array 3604 // edi: elements array
3603 // ebx: untagged index 3605 // ebx: untagged index
3604 __ test(eax, Immediate(kSmiTagMask)); 3606 if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) {
3605 if (array_type == kExternalPixelArray) 3607 __ JumpIfNotSmi(eax, &slow);
3606 __ j(not_equal, &slow); 3608 } else {
3607 else 3609 __ JumpIfNotSmi(eax, &check_heap_number);
3608 __ j(not_equal, &check_heap_number); 3610 }
3609 3611
3610 // smi case 3612 // smi case
3611 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. 3613 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed.
3612 __ SmiUntag(ecx); 3614 __ SmiUntag(ecx);
3613 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3615 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3614 // ecx: base pointer of external storage 3616 // ecx: base pointer of external storage
3615 switch (array_type) { 3617 switch (elements_kind) {
3616 case kExternalPixelArray: 3618 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3617 { // Clamp the value to [0..255]. 3619 { // Clamp the value to [0..255].
3618 Label done; 3620 Label done;
3619 __ test(ecx, Immediate(0xFFFFFF00)); 3621 __ test(ecx, Immediate(0xFFFFFF00));
3620 __ j(zero, &done, Label::kNear); 3622 __ j(zero, &done, Label::kNear);
3621 __ setcc(negative, ecx); // 1 if negative, 0 if positive. 3623 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
3622 __ dec_b(ecx); // 0 if negative, 255 if positive. 3624 __ dec_b(ecx); // 0 if negative, 255 if positive.
3623 __ bind(&done); 3625 __ bind(&done);
3624 } 3626 }
3625 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3627 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3626 break; 3628 break;
3627 case kExternalByteArray: 3629 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3628 case kExternalUnsignedByteArray: 3630 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3629 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3631 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3630 break; 3632 break;
3631 case kExternalShortArray: 3633 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3632 case kExternalUnsignedShortArray: 3634 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3633 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 3635 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
3634 break; 3636 break;
3635 case kExternalIntArray: 3637 case JSObject::EXTERNAL_INT_ELEMENTS:
3636 case kExternalUnsignedIntArray: 3638 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3637 __ mov(Operand(edi, ebx, times_4, 0), ecx); 3639 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3638 break; 3640 break;
3639 case kExternalFloatArray: 3641 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3640 case kExternalDoubleArray: 3642 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3641 // Need to perform int-to-float conversion. 3643 // Need to perform int-to-float conversion.
3642 __ push(ecx); 3644 __ push(ecx);
3643 __ fild_s(Operand(esp, 0)); 3645 __ fild_s(Operand(esp, 0));
3644 __ pop(ecx); 3646 __ pop(ecx);
3645 if (array_type == kExternalFloatArray) { 3647 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
3646 __ fstp_s(Operand(edi, ebx, times_4, 0)); 3648 __ fstp_s(Operand(edi, ebx, times_4, 0));
3647 } else { // array_type == kExternalDoubleArray. 3649 } else { // elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS.
3648 __ fstp_d(Operand(edi, ebx, times_8, 0)); 3650 __ fstp_d(Operand(edi, ebx, times_8, 0));
3649 } 3651 }
3650 break; 3652 break;
3651 default: 3653 default:
3652 UNREACHABLE(); 3654 UNREACHABLE();
3653 break; 3655 break;
3654 } 3656 }
3655 __ ret(0); // Return the original value. 3657 __ ret(0); // Return the original value.
3656 3658
3657 // TODO(danno): handle heap number -> pixel array conversion 3659 // TODO(danno): handle heap number -> pixel array conversion
3658 if (array_type != kExternalPixelArray) { 3660 if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) {
3659 __ bind(&check_heap_number); 3661 __ bind(&check_heap_number);
3660 // eax: value 3662 // eax: value
3661 // edx: receiver 3663 // edx: receiver
3662 // ecx: key 3664 // ecx: key
3663 // edi: elements array 3665 // edi: elements array
3664 // ebx: untagged index 3666 // ebx: untagged index
3665 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3667 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3666 Immediate(masm->isolate()->factory()->heap_number_map())); 3668 Immediate(masm->isolate()->factory()->heap_number_map()));
3667 __ j(not_equal, &slow); 3669 __ j(not_equal, &slow);
3668 3670
3669 // The WebGL specification leaves the behavior of storing NaN and 3671 // The WebGL specification leaves the behavior of storing NaN and
3670 // +/-Infinity into integer arrays basically undefined. For more 3672 // +/-Infinity into integer arrays basically undefined. For more
3671 // reproducible behavior, convert these to zero. 3673 // reproducible behavior, convert these to zero.
3672 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3674 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3673 // ebx: untagged index 3675 // ebx: untagged index
3674 // edi: base pointer of external storage 3676 // edi: base pointer of external storage
3675 if (array_type == kExternalFloatArray) { 3677 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
3676 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3678 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
3677 __ fstp_s(Operand(edi, ebx, times_4, 0)); 3679 __ fstp_s(Operand(edi, ebx, times_4, 0));
3678 __ ret(0); 3680 __ ret(0);
3679 } else if (array_type == kExternalDoubleArray) { 3681 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
3680 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3682 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
3681 __ fstp_d(Operand(edi, ebx, times_8, 0)); 3683 __ fstp_d(Operand(edi, ebx, times_8, 0));
3682 __ ret(0); 3684 __ ret(0);
3683 } else { 3685 } else {
3684 // Perform float-to-int conversion with truncation (round-to-zero) 3686 // Perform float-to-int conversion with truncation (round-to-zero)
3685 // behavior. 3687 // behavior.
3686 3688
3687 // For the moment we make the slow call to the runtime on 3689 // For the moment we make the slow call to the runtime on
3688 // processors that don't support SSE2. The code in IntegerConvert 3690 // processors that don't support SSE2. The code in IntegerConvert
3689 // (code-stubs-ia32.cc) is roughly what is needed here though the 3691 // (code-stubs-ia32.cc) is roughly what is needed here though the
3690 // conversion failure case does not need to be handled. 3692 // conversion failure case does not need to be handled.
3691 if (CpuFeatures::IsSupported(SSE2)) { 3693 if (CpuFeatures::IsSupported(SSE2)) {
3692 if (array_type != kExternalIntArray && 3694 if (elements_kind != JSObject::EXTERNAL_INT_ELEMENTS &&
3693 array_type != kExternalUnsignedIntArray) { 3695 elements_kind != JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) {
3694 ASSERT(CpuFeatures::IsSupported(SSE2)); 3696 ASSERT(CpuFeatures::IsSupported(SSE2));
3695 CpuFeatures::Scope scope(SSE2); 3697 CpuFeatures::Scope scope(SSE2);
3696 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); 3698 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
3697 // ecx: untagged integer value 3699 // ecx: untagged integer value
3698 switch (array_type) { 3700 switch (elements_kind) {
3699 case kExternalPixelArray: 3701 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3700 { // Clamp the value to [0..255]. 3702 { // Clamp the value to [0..255].
3701 Label done; 3703 Label done;
3702 __ test(ecx, Immediate(0xFFFFFF00)); 3704 __ test(ecx, Immediate(0xFFFFFF00));
3703 __ j(zero, &done, Label::kNear); 3705 __ j(zero, &done, Label::kNear);
3704 __ setcc(negative, ecx); // 1 if negative, 0 if positive. 3706 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
3705 __ dec_b(ecx); // 0 if negative, 255 if positive. 3707 __ dec_b(ecx); // 0 if negative, 255 if positive.
3706 __ bind(&done); 3708 __ bind(&done);
3707 } 3709 }
3708 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3710 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3709 break; 3711 break;
3710 case kExternalByteArray: 3712 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3711 case kExternalUnsignedByteArray: 3713 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3712 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3714 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3713 break; 3715 break;
3714 case kExternalShortArray: 3716 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3715 case kExternalUnsignedShortArray: 3717 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3716 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 3718 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
3717 break; 3719 break;
3718 default: 3720 default:
3719 UNREACHABLE(); 3721 UNREACHABLE();
3720 break; 3722 break;
3721 } 3723 }
3722 } else { 3724 } else {
3723 if (CpuFeatures::IsSupported(SSE3)) { 3725 if (CpuFeatures::IsSupported(SSE3)) {
3724 CpuFeatures::Scope scope(SSE3); 3726 CpuFeatures::Scope scope(SSE3);
3725 // fisttp stores values as signed integers. To represent the 3727 // fisttp stores values as signed integers. To represent the
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3778 // -- esp[0] : return address 3780 // -- esp[0] : return address
3779 // ----------------------------------- 3781 // -----------------------------------
3780 3782
3781 __ bind(&miss_force_generic); 3783 __ bind(&miss_force_generic);
3782 Handle<Code> miss_ic = 3784 Handle<Code> miss_ic =
3783 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3785 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3784 __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3786 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3785 } 3787 }
3786 3788
3787 3789
3788
3789
3790 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 3790 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3791 // ----------- S t a t e ------------- 3791 // ----------- S t a t e -------------
3792 // -- eax : key 3792 // -- eax : key
3793 // -- edx : receiver 3793 // -- edx : receiver
3794 // -- esp[0] : return address 3794 // -- esp[0] : return address
3795 // ----------------------------------- 3795 // -----------------------------------
3796 Label miss_force_generic; 3796 Label miss_force_generic;
3797 3797
3798 // This stub is meant to be tail-jumped to, the receiver must already 3798 // This stub is meant to be tail-jumped to, the receiver must already
3799 // have been verified by the caller to not be a smi. 3799 // have been verified by the caller to not be a smi.
3800 3800
3801 // Check that the key is a smi. 3801 // Check that the key is a smi.
3802 __ test(eax, Immediate(kSmiTagMask)); 3802 __ JumpIfNotSmi(eax, &miss_force_generic);
3803 __ j(not_zero, &miss_force_generic);
3804 3803
3805 // Get the elements array. 3804 // Get the elements array.
3806 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset)); 3805 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3807 __ AssertFastElements(ecx); 3806 __ AssertFastElements(ecx);
3808 3807
3809 // Check that the key is within bounds. 3808 // Check that the key is within bounds.
3810 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset)); 3809 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3811 __ j(above_equal, &miss_force_generic); 3810 __ j(above_equal, &miss_force_generic);
3812 3811
3813 // Load the result and make sure it's not the hole. 3812 // Load the result and make sure it's not the hole.
3814 __ mov(ebx, Operand(ecx, eax, times_2, 3813 __ mov(ebx, Operand(ecx, eax, times_2,
3815 FixedArray::kHeaderSize - kHeapObjectTag)); 3814 FixedArray::kHeaderSize - kHeapObjectTag));
3816 __ cmp(ebx, masm->isolate()->factory()->the_hole_value()); 3815 __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
3817 __ j(equal, &miss_force_generic); 3816 __ j(equal, &miss_force_generic);
3818 __ mov(eax, ebx); 3817 __ mov(eax, ebx);
3819 __ ret(0); 3818 __ ret(0);
3820 3819
3821 __ bind(&miss_force_generic); 3820 __ bind(&miss_force_generic);
3822 Handle<Code> miss_ic = 3821 Handle<Code> miss_ic =
3823 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3822 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3824 __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3823 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3825 } 3824 }
3826 3825
3827 3826
3828 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm, 3827 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3829 bool is_js_array) { 3828 bool is_js_array) {
3830 // ----------- S t a t e ------------- 3829 // ----------- S t a t e -------------
3831 // -- eax : key 3830 // -- eax : value
3831 // -- ecx : key
3832 // -- edx : receiver 3832 // -- edx : receiver
3833 // -- esp[0] : return address 3833 // -- esp[0] : return address
3834 // ----------------------------------- 3834 // -----------------------------------
3835 Label miss_force_generic; 3835 Label miss_force_generic;
3836 3836
3837 // This stub is meant to be tail-jumped to, the receiver must already 3837 // This stub is meant to be tail-jumped to, the receiver must already
3838 // have been verified by the caller to not be a smi. 3838 // have been verified by the caller to not be a smi.
3839 3839
3840 // Check that the key is a smi. 3840 // Check that the key is a smi.
3841 __ test(ecx, Immediate(kSmiTagMask)); 3841 __ JumpIfNotSmi(ecx, &miss_force_generic);
3842 __ j(not_zero, &miss_force_generic);
3843 3842
3844 // Get the elements array and make sure it is a fast element array, not 'cow'. 3843 // Get the elements array and make sure it is a fast element array, not 'cow'.
3845 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3844 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3846 __ cmp(FieldOperand(edi, HeapObject::kMapOffset), 3845 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3847 Immediate(masm->isolate()->factory()->fixed_array_map())); 3846 Immediate(masm->isolate()->factory()->fixed_array_map()));
3848 __ j(not_equal, &miss_force_generic); 3847 __ j(not_equal, &miss_force_generic);
3849 3848
3850 if (is_js_array) { 3849 if (is_js_array) {
3851 // Check that the key is within bounds. 3850 // Check that the key is within bounds.
3852 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis. 3851 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
(...skipping 20 matching lines...) Expand all
3873 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3872 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3874 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3873 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3875 } 3874 }
3876 3875
3877 3876
3878 #undef __ 3877 #undef __
3879 3878
3880 } } // namespace v8::internal 3879 } } // namespace v8::internal
3881 3880
3882 #endif // V8_TARGET_ARCH_IA32 3881 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/regexp-macro-assembler-ia32.h ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698