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

Side by Side Diff: src/arm/stub-cache-arm.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/arm/regexp-macro-assembler-arm.cc ('k') | src/array.js » ('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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 114
115 // Bail out if the receiver has a named interceptor or requires access checks. 115 // Bail out if the receiver has a named interceptor or requires access checks.
116 Register map = scratch1; 116 Register map = scratch1;
117 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 117 __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
118 __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 118 __ ldrb(scratch0, FieldMemOperand(map, Map::kBitFieldOffset));
119 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 119 __ tst(scratch0, Operand(kInterceptorOrAccessCheckNeededMask));
120 __ b(ne, miss_label); 120 __ b(ne, miss_label);
121 121
122 // Check that receiver is a JSObject. 122 // Check that receiver is a JSObject.
123 __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 123 __ ldrb(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset));
124 __ cmp(scratch0, Operand(FIRST_JS_OBJECT_TYPE)); 124 __ cmp(scratch0, Operand(FIRST_SPEC_OBJECT_TYPE));
125 __ b(lt, miss_label); 125 __ b(lt, miss_label);
126 126
127 // Load properties array. 127 // Load properties array.
128 Register properties = scratch0; 128 Register properties = scratch0;
129 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 129 __ ldr(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset));
130 // Check that the properties array is a dictionary. 130 // Check that the properties array is a dictionary.
131 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 131 __ ldr(map, FieldMemOperand(properties, HeapObject::kMapOffset));
132 Register tmp = properties; 132 Register tmp = properties;
133 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 133 __ LoadRoot(tmp, Heap::kHashTableMapRootIndex);
134 __ cmp(map, tmp); 134 __ cmp(map, tmp);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 ASSERT(!extra2.is(name)); 182 ASSERT(!extra2.is(name));
183 ASSERT(!extra2.is(scratch)); 183 ASSERT(!extra2.is(scratch));
184 ASSERT(!extra2.is(extra)); 184 ASSERT(!extra2.is(extra));
185 185
186 // Check scratch, extra and extra2 registers are valid. 186 // Check scratch, extra and extra2 registers are valid.
187 ASSERT(!scratch.is(no_reg)); 187 ASSERT(!scratch.is(no_reg));
188 ASSERT(!extra.is(no_reg)); 188 ASSERT(!extra.is(no_reg));
189 ASSERT(!extra2.is(no_reg)); 189 ASSERT(!extra2.is(no_reg));
190 190
191 // Check that the receiver isn't a smi. 191 // Check that the receiver isn't a smi.
192 __ tst(receiver, Operand(kSmiTagMask)); 192 __ JumpIfSmi(receiver, &miss);
193 __ b(eq, &miss);
194 193
195 // Get the map of the receiver and compute the hash. 194 // Get the map of the receiver and compute the hash.
196 __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset)); 195 __ ldr(scratch, FieldMemOperand(name, String::kHashFieldOffset));
197 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset)); 196 __ ldr(ip, FieldMemOperand(receiver, HeapObject::kMapOffset));
198 __ add(scratch, scratch, Operand(ip)); 197 __ add(scratch, scratch, Operand(ip));
199 __ eor(scratch, scratch, Operand(flags)); 198 __ eor(scratch, scratch, Operand(flags));
200 __ and_(scratch, 199 __ and_(scratch,
201 scratch, 200 scratch,
202 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize)); 201 Operand((kPrimaryTableSize - 1) << kHeapObjectTagSize));
203 202
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 __ ldr(dst, FieldMemOperand(dst, offset)); 274 __ ldr(dst, FieldMemOperand(dst, offset));
276 } 275 }
277 } 276 }
278 277
279 278
280 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 279 void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
281 Register receiver, 280 Register receiver,
282 Register scratch, 281 Register scratch,
283 Label* miss_label) { 282 Label* miss_label) {
284 // Check that the receiver isn't a smi. 283 // Check that the receiver isn't a smi.
285 __ tst(receiver, Operand(kSmiTagMask)); 284 __ JumpIfSmi(receiver, miss_label);
286 __ b(eq, miss_label);
287 285
288 // Check that the object is a JS array. 286 // Check that the object is a JS array.
289 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE); 287 __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
290 __ b(ne, miss_label); 288 __ b(ne, miss_label);
291 289
292 // Load length directly from the JS array. 290 // Load length directly from the JS array.
293 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 291 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
294 __ Ret(); 292 __ Ret();
295 } 293 }
296 294
297 295
298 // Generate code to check if an object is a string. If the object is a 296 // Generate code to check if an object is a string. If the object is a
299 // heap object, its map's instance type is left in the scratch1 register. 297 // heap object, its map's instance type is left in the scratch1 register.
300 // If this is not needed, scratch1 and scratch2 may be the same register. 298 // If this is not needed, scratch1 and scratch2 may be the same register.
301 static void GenerateStringCheck(MacroAssembler* masm, 299 static void GenerateStringCheck(MacroAssembler* masm,
302 Register receiver, 300 Register receiver,
303 Register scratch1, 301 Register scratch1,
304 Register scratch2, 302 Register scratch2,
305 Label* smi, 303 Label* smi,
306 Label* non_string_object) { 304 Label* non_string_object) {
307 // Check that the receiver isn't a smi. 305 // Check that the receiver isn't a smi.
308 __ tst(receiver, Operand(kSmiTagMask)); 306 __ JumpIfSmi(receiver, smi);
309 __ b(eq, smi);
310 307
311 // Check that the object is a string. 308 // Check that the object is a string.
312 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); 309 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
313 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 310 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
314 __ and_(scratch2, scratch1, Operand(kIsNotStringMask)); 311 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
315 // The cast is to resolve the overload for the argument of 0x0. 312 // The cast is to resolve the overload for the argument of 0x0.
316 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag))); 313 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
317 __ b(ne, non_string_object); 314 __ b(ne, non_string_object);
318 } 315 }
319 316
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 int index, 371 int index,
375 Map* transition, 372 Map* transition,
376 Register receiver_reg, 373 Register receiver_reg,
377 Register name_reg, 374 Register name_reg,
378 Register scratch, 375 Register scratch,
379 Label* miss_label) { 376 Label* miss_label) {
380 // r0 : value 377 // r0 : value
381 Label exit; 378 Label exit;
382 379
383 // Check that the receiver isn't a smi. 380 // Check that the receiver isn't a smi.
384 __ tst(receiver_reg, Operand(kSmiTagMask)); 381 __ JumpIfSmi(receiver_reg, miss_label);
385 __ b(eq, miss_label);
386 382
387 // Check that the map of the receiver hasn't changed. 383 // Check that the map of the receiver hasn't changed.
388 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 384 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
389 __ cmp(scratch, Operand(Handle<Map>(object->map()))); 385 __ cmp(scratch, Operand(Handle<Map>(object->map())));
390 __ b(ne, miss_label); 386 __ b(ne, miss_label);
391 387
392 // Perform global security token check if needed. 388 // Perform global security token check if needed.
393 if (object->IsJSGlobalProxy()) { 389 if (object->IsJSGlobalProxy()) {
394 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 390 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
395 } 391 }
(...skipping 27 matching lines...) Expand all
423 // Adjust for the number of properties stored in the object. Even in the 419 // Adjust for the number of properties stored in the object. Even in the
424 // face of a transition we can use the old map here because the size of the 420 // face of a transition we can use the old map here because the size of the
425 // object and the number of in-object properties is not going to change. 421 // object and the number of in-object properties is not going to change.
426 index -= object->map()->inobject_properties(); 422 index -= object->map()->inobject_properties();
427 423
428 if (index < 0) { 424 if (index < 0) {
429 // Set the property straight into the object. 425 // Set the property straight into the object.
430 int offset = object->map()->instance_size() + (index * kPointerSize); 426 int offset = object->map()->instance_size() + (index * kPointerSize);
431 __ str(r0, FieldMemOperand(receiver_reg, offset)); 427 __ str(r0, FieldMemOperand(receiver_reg, offset));
432 428
429 // Skip updating write barrier if storing a smi.
430 __ JumpIfSmi(r0, &exit);
431
433 // Update the write barrier for the array address. 432 // Update the write barrier for the array address.
434 // Pass the now unused name_reg as a scratch register. 433 // Pass the now unused name_reg as a scratch register.
435 __ mov(name_reg, r0); 434 __ mov(name_reg, r0);
436 __ RecordWriteField(receiver_reg, 435 __ RecordWriteField(receiver_reg,
437 offset, 436 offset,
438 name_reg, 437 name_reg,
439 scratch, 438 scratch,
440 kLRHasNotBeenSaved, 439 kLRHasNotBeenSaved,
441 kDontSaveFPRegs); 440 kDontSaveFPRegs);
442 } else { 441 } else {
443 // Write to the properties array. 442 // Write to the properties array.
444 int offset = index * kPointerSize + FixedArray::kHeaderSize; 443 int offset = index * kPointerSize + FixedArray::kHeaderSize;
445 // Get the properties array 444 // Get the properties array
446 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); 445 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
447 __ str(r0, FieldMemOperand(scratch, offset)); 446 __ str(r0, FieldMemOperand(scratch, offset));
448 447
448 // Skip updating write barrier if storing a smi.
449 __ JumpIfSmi(r0, &exit);
450
449 // Update the write barrier for the array address. 451 // Update the write barrier for the array address.
450 // Ok to clobber receiver_reg and name_reg, since we return. 452 // Ok to clobber receiver_reg and name_reg, since we return.
451 __ mov(name_reg, r0); 453 __ mov(name_reg, r0);
452 __ RecordWriteField(scratch, 454 __ RecordWriteField(scratch,
453 offset, 455 offset,
454 name_reg, 456 name_reg,
455 receiver_reg, 457 receiver_reg,
456 kLRHasNotBeenSaved, 458 kLRHasNotBeenSaved,
457 kDontSaveFPRegs); 459 kDontSaveFPRegs);
458 } 460 }
(...skipping 14 matching lines...) Expand all
473 } 475 }
474 476
475 Handle<Code> ic(code); 477 Handle<Code> ic(code);
476 __ Jump(ic, RelocInfo::CODE_TARGET); 478 __ Jump(ic, RelocInfo::CODE_TARGET);
477 } 479 }
478 480
479 481
480 static void GenerateCallFunction(MacroAssembler* masm, 482 static void GenerateCallFunction(MacroAssembler* masm,
481 Object* object, 483 Object* object,
482 const ParameterCount& arguments, 484 const ParameterCount& arguments,
483 Label* miss) { 485 Label* miss,
486 Code::ExtraICState extra_ic_state) {
484 // ----------- S t a t e ------------- 487 // ----------- S t a t e -------------
485 // -- r0: receiver 488 // -- r0: receiver
486 // -- r1: function to call 489 // -- r1: function to call
487 // ----------------------------------- 490 // -----------------------------------
488 491
489 // Check that the function really is a function. 492 // Check that the function really is a function.
490 __ JumpIfSmi(r1, miss); 493 __ JumpIfSmi(r1, miss);
491 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 494 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
492 __ b(ne, miss); 495 __ b(ne, miss);
493 496
494 // Patch the receiver on the stack with the global proxy if 497 // Patch the receiver on the stack with the global proxy if
495 // necessary. 498 // necessary.
496 if (object->IsGlobalObject()) { 499 if (object->IsGlobalObject()) {
497 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); 500 __ ldr(r3, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
498 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize)); 501 __ str(r3, MemOperand(sp, arguments.immediate() * kPointerSize));
499 } 502 }
500 503
501 // Invoke the function. 504 // Invoke the function.
502 __ InvokeFunction(r1, arguments, JUMP_FUNCTION); 505 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state)
506 ? CALL_AS_FUNCTION
507 : CALL_AS_METHOD;
508 __ InvokeFunction(r1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind);
503 } 509 }
504 510
505 511
506 static void PushInterceptorArguments(MacroAssembler* masm, 512 static void PushInterceptorArguments(MacroAssembler* masm,
507 Register receiver, 513 Register receiver,
508 Register holder, 514 Register holder,
509 Register name, 515 Register name,
510 JSObject* holder_obj) { 516 JSObject* holder_obj) {
511 __ push(name); 517 __ push(name);
512 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor(); 518 InterceptorInfo* interceptor = holder_obj->GetNamedInterceptor();
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 ExternalReference ref = ExternalReference(&fun, 628 ExternalReference ref = ExternalReference(&fun,
623 ExternalReference::DIRECT_API_CALL, 629 ExternalReference::DIRECT_API_CALL,
624 masm->isolate()); 630 masm->isolate());
625 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); 631 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
626 } 632 }
627 633
628 class CallInterceptorCompiler BASE_EMBEDDED { 634 class CallInterceptorCompiler BASE_EMBEDDED {
629 public: 635 public:
630 CallInterceptorCompiler(StubCompiler* stub_compiler, 636 CallInterceptorCompiler(StubCompiler* stub_compiler,
631 const ParameterCount& arguments, 637 const ParameterCount& arguments,
632 Register name) 638 Register name,
639 Code::ExtraICState extra_ic_state)
633 : stub_compiler_(stub_compiler), 640 : stub_compiler_(stub_compiler),
634 arguments_(arguments), 641 arguments_(arguments),
635 name_(name) {} 642 name_(name),
643 extra_ic_state_(extra_ic_state) {}
636 644
637 MaybeObject* Compile(MacroAssembler* masm, 645 MaybeObject* Compile(MacroAssembler* masm,
638 JSObject* object, 646 JSObject* object,
639 JSObject* holder, 647 JSObject* holder,
640 String* name, 648 String* name,
641 LookupResult* lookup, 649 LookupResult* lookup,
642 Register receiver, 650 Register receiver,
643 Register scratch1, 651 Register scratch1,
644 Register scratch2, 652 Register scratch2,
645 Register scratch3, 653 Register scratch3,
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
753 ASSERT(depth2 == kInvalidProtoDepth); 761 ASSERT(depth2 == kInvalidProtoDepth);
754 } 762 }
755 763
756 // Invoke function. 764 // Invoke function.
757 if (can_do_fast_api_call) { 765 if (can_do_fast_api_call) {
758 MaybeObject* result = GenerateFastApiDirectCall(masm, 766 MaybeObject* result = GenerateFastApiDirectCall(masm,
759 optimization, 767 optimization,
760 arguments_.immediate()); 768 arguments_.immediate());
761 if (result->IsFailure()) return result; 769 if (result->IsFailure()) return result;
762 } else { 770 } else {
771 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
772 ? CALL_AS_FUNCTION
773 : CALL_AS_METHOD;
763 __ InvokeFunction(optimization.constant_function(), arguments_, 774 __ InvokeFunction(optimization.constant_function(), arguments_,
764 JUMP_FUNCTION); 775 JUMP_FUNCTION, call_kind);
765 } 776 }
766 777
767 // Deferred code for fast API call case---clean preallocated space. 778 // Deferred code for fast API call case---clean preallocated space.
768 if (can_do_fast_api_call) { 779 if (can_do_fast_api_call) {
769 __ bind(&miss_cleanup); 780 __ bind(&miss_cleanup);
770 FreeSpaceForFastApiCall(masm); 781 FreeSpaceForFastApiCall(masm);
771 __ b(miss_label); 782 __ b(miss_label);
772 } 783 }
773 784
774 // Invoke a regular function. 785 // Invoke a regular function.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
836 847
837 // If interceptor returns no-result sentinel, call the constant function. 848 // If interceptor returns no-result sentinel, call the constant function.
838 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); 849 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex);
839 __ cmp(r0, scratch); 850 __ cmp(r0, scratch);
840 __ b(ne, interceptor_succeeded); 851 __ b(ne, interceptor_succeeded);
841 } 852 }
842 853
843 StubCompiler* stub_compiler_; 854 StubCompiler* stub_compiler_;
844 const ParameterCount& arguments_; 855 const ParameterCount& arguments_;
845 Register name_; 856 Register name_;
857 Code::ExtraICState extra_ic_state_;
846 }; 858 };
847 859
848 860
849 // Generate code to check that a global property cell is empty. Create 861 // Generate code to check that a global property cell is empty. Create
850 // the property cell at compilation time if no cell exists for the 862 // the property cell at compilation time if no cell exists for the
851 // property. 863 // property.
852 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell( 864 MUST_USE_RESULT static MaybeObject* GenerateCheckPropertyCell(
853 MacroAssembler* masm, 865 MacroAssembler* masm,
854 GlobalObject* global, 866 GlobalObject* global,
855 String* name, 867 String* name,
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 void StubCompiler::GenerateLoadField(JSObject* object, 1164 void StubCompiler::GenerateLoadField(JSObject* object,
1153 JSObject* holder, 1165 JSObject* holder,
1154 Register receiver, 1166 Register receiver,
1155 Register scratch1, 1167 Register scratch1,
1156 Register scratch2, 1168 Register scratch2,
1157 Register scratch3, 1169 Register scratch3,
1158 int index, 1170 int index,
1159 String* name, 1171 String* name,
1160 Label* miss) { 1172 Label* miss) {
1161 // Check that the receiver isn't a smi. 1173 // Check that the receiver isn't a smi.
1162 __ tst(receiver, Operand(kSmiTagMask)); 1174 __ JumpIfSmi(receiver, miss);
1163 __ b(eq, miss);
1164 1175
1165 // Check that the maps haven't changed. 1176 // Check that the maps haven't changed.
1166 Register reg = 1177 Register reg =
1167 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, 1178 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
1168 name, miss); 1179 name, miss);
1169 GenerateFastPropertyLoad(masm(), r0, reg, holder, index); 1180 GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
1170 __ Ret(); 1181 __ Ret();
1171 } 1182 }
1172 1183
1173 1184
1174 void StubCompiler::GenerateLoadConstant(JSObject* object, 1185 void StubCompiler::GenerateLoadConstant(JSObject* object,
1175 JSObject* holder, 1186 JSObject* holder,
1176 Register receiver, 1187 Register receiver,
1177 Register scratch1, 1188 Register scratch1,
1178 Register scratch2, 1189 Register scratch2,
1179 Register scratch3, 1190 Register scratch3,
1180 Object* value, 1191 Object* value,
1181 String* name, 1192 String* name,
1182 Label* miss) { 1193 Label* miss) {
1183 // Check that the receiver isn't a smi. 1194 // Check that the receiver isn't a smi.
1184 __ tst(receiver, Operand(kSmiTagMask)); 1195 __ JumpIfSmi(receiver, miss);
1185 __ b(eq, miss);
1186 1196
1187 // Check that the maps haven't changed. 1197 // Check that the maps haven't changed.
1188 Register reg = 1198 Register reg =
1189 CheckPrototypes(object, receiver, holder, 1199 CheckPrototypes(object, receiver, holder,
1190 scratch1, scratch2, scratch3, name, miss); 1200 scratch1, scratch2, scratch3, name, miss);
1191 1201
1192 // Return the constant value. 1202 // Return the constant value.
1193 __ mov(r0, Operand(Handle<Object>(value))); 1203 __ mov(r0, Operand(Handle<Object>(value)));
1194 __ Ret(); 1204 __ Ret();
1195 } 1205 }
1196 1206
1197 1207
1198 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object, 1208 MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
1199 JSObject* holder, 1209 JSObject* holder,
1200 Register receiver, 1210 Register receiver,
1201 Register name_reg, 1211 Register name_reg,
1202 Register scratch1, 1212 Register scratch1,
1203 Register scratch2, 1213 Register scratch2,
1204 Register scratch3, 1214 Register scratch3,
1205 AccessorInfo* callback, 1215 AccessorInfo* callback,
1206 String* name, 1216 String* name,
1207 Label* miss) { 1217 Label* miss) {
1208 // Check that the receiver isn't a smi. 1218 // Check that the receiver isn't a smi.
1209 __ tst(receiver, Operand(kSmiTagMask)); 1219 __ JumpIfSmi(receiver, miss);
1210 __ b(eq, miss);
1211 1220
1212 // Check that the maps haven't changed. 1221 // Check that the maps haven't changed.
1213 Register reg = 1222 Register reg =
1214 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, 1223 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
1215 name, miss); 1224 name, miss);
1216 1225
1217 // Build AccessorInfo::args_ list on the stack and push property name below 1226 // Build AccessorInfo::args_ list on the stack and push property name below
1218 // the exit frame to make GC aware of them and store pointers to them. 1227 // the exit frame to make GC aware of them and store pointers to them.
1219 __ push(receiver); 1228 __ push(receiver);
1220 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ 1229 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1413 // Get the number of arguments. 1422 // Get the number of arguments.
1414 const int argc = arguments().immediate(); 1423 const int argc = arguments().immediate();
1415 1424
1416 // Get the receiver from the stack. 1425 // Get the receiver from the stack.
1417 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1426 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1418 1427
1419 // If the object is the holder then we know that it's a global 1428 // If the object is the holder then we know that it's a global
1420 // object which can only happen for contextual calls. In this case, 1429 // object which can only happen for contextual calls. In this case,
1421 // the receiver cannot be a smi. 1430 // the receiver cannot be a smi.
1422 if (object != holder) { 1431 if (object != holder) {
1423 __ tst(r0, Operand(kSmiTagMask)); 1432 __ JumpIfSmi(r0, miss);
1424 __ b(eq, miss);
1425 } 1433 }
1426 1434
1427 // Check that the maps haven't changed. 1435 // Check that the maps haven't changed.
1428 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss); 1436 CheckPrototypes(object, r0, holder, r3, r1, r4, name, miss);
1429 } 1437 }
1430 1438
1431 1439
1432 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell, 1440 void CallStubCompiler::GenerateLoadFunctionFromCell(JSGlobalPropertyCell* cell,
1433 JSFunction* function, 1441 JSFunction* function,
1434 Label* miss) { 1442 Label* miss) {
1435 // Get the value from the cell. 1443 // Get the value from the cell.
1436 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 1444 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
1437 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 1445 __ ldr(r1, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
1438 1446
1439 // Check that the cell contains the same function. 1447 // Check that the cell contains the same function.
1440 if (heap()->InNewSpace(function)) { 1448 if (heap()->InNewSpace(function)) {
1441 // We can't embed a pointer to a function in new space so we have 1449 // We can't embed a pointer to a function in new space so we have
1442 // to verify that the shared function info is unchanged. This has 1450 // to verify that the shared function info is unchanged. This has
1443 // the nice side effect that multiple closures based on the same 1451 // the nice side effect that multiple closures based on the same
1444 // function can all use this call IC. Before we load through the 1452 // function can all use this call IC. Before we load through the
1445 // function, we have to verify that it still is a function. 1453 // function, we have to verify that it still is a function.
1446 __ tst(r1, Operand(kSmiTagMask)); 1454 __ JumpIfSmi(r1, miss);
1447 __ b(eq, miss);
1448 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE); 1455 __ CompareObjectType(r1, r3, r3, JS_FUNCTION_TYPE);
1449 __ b(ne, miss); 1456 __ b(ne, miss);
1450 1457
1451 // Check the shared function info. Make sure it hasn't changed. 1458 // Check the shared function info. Make sure it hasn't changed.
1452 __ Move(r3, Handle<SharedFunctionInfo>(function->shared())); 1459 __ Move(r3, Handle<SharedFunctionInfo>(function->shared()));
1453 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 1460 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
1454 __ cmp(r4, r3); 1461 __ cmp(r4, r3);
1455 __ b(ne, miss); 1462 __ b(ne, miss);
1456 } else { 1463 } else {
1457 __ cmp(r1, Operand(Handle<JSFunction>(function))); 1464 __ cmp(r1, Operand(Handle<JSFunction>(function)));
(...skipping 24 matching lines...) Expand all
1482 // ----------------------------------- 1489 // -----------------------------------
1483 Label miss; 1490 Label miss;
1484 1491
1485 GenerateNameCheck(name, &miss); 1492 GenerateNameCheck(name, &miss);
1486 1493
1487 const int argc = arguments().immediate(); 1494 const int argc = arguments().immediate();
1488 1495
1489 // Get the receiver of the function from the stack into r0. 1496 // Get the receiver of the function from the stack into r0.
1490 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 1497 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
1491 // Check that the receiver isn't a smi. 1498 // Check that the receiver isn't a smi.
1492 __ tst(r0, Operand(kSmiTagMask)); 1499 __ JumpIfSmi(r0, &miss);
1493 __ b(eq, &miss);
1494 1500
1495 // Do the right check and compute the holder register. 1501 // Do the right check and compute the holder register.
1496 Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss); 1502 Register reg = CheckPrototypes(object, r0, holder, r1, r3, r4, name, &miss);
1497 GenerateFastPropertyLoad(masm(), r1, reg, holder, index); 1503 GenerateFastPropertyLoad(masm(), r1, reg, holder, index);
1498 1504
1499 GenerateCallFunction(masm(), object, arguments(), &miss); 1505 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_);
1500 1506
1501 // Handle call cache miss. 1507 // Handle call cache miss.
1502 __ bind(&miss); 1508 __ bind(&miss);
1503 MaybeObject* maybe_result = GenerateMissBranch(); 1509 MaybeObject* maybe_result = GenerateMissBranch();
1504 if (maybe_result->IsFailure()) return maybe_result; 1510 if (maybe_result->IsFailure()) return maybe_result;
1505 1511
1506 // Return the generated code. 1512 // Return the generated code.
1507 return GetCode(FIELD, name); 1513 return GetCode(FIELD, name);
1508 } 1514 }
1509 1515
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
1960 // arguments, bail out to the regular call. 1966 // arguments, bail out to the regular call.
1961 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); 1967 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
1962 1968
1963 Label miss; 1969 Label miss;
1964 GenerateNameCheck(name, &miss); 1970 GenerateNameCheck(name, &miss);
1965 1971
1966 if (cell == NULL) { 1972 if (cell == NULL) {
1967 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 1973 __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
1968 1974
1969 STATIC_ASSERT(kSmiTag == 0); 1975 STATIC_ASSERT(kSmiTag == 0);
1970 __ tst(r1, Operand(kSmiTagMask)); 1976 __ JumpIfSmi(r1, &miss);
1971 __ b(eq, &miss);
1972 1977
1973 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, 1978 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
1974 &miss); 1979 &miss);
1975 } else { 1980 } else {
1976 ASSERT(cell->value() == function); 1981 ASSERT(cell->value() == function);
1977 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 1982 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
1978 GenerateLoadFunctionFromCell(cell, function, &miss); 1983 GenerateLoadFunctionFromCell(cell, function, &miss);
1979 } 1984 }
1980 1985
1981 // Load the char code argument. 1986 // Load the char code argument.
1982 Register code = r1; 1987 Register code = r1;
1983 __ ldr(code, MemOperand(sp, 0 * kPointerSize)); 1988 __ ldr(code, MemOperand(sp, 0 * kPointerSize));
1984 1989
1985 // Check the code is a smi. 1990 // Check the code is a smi.
1986 Label slow; 1991 Label slow;
1987 STATIC_ASSERT(kSmiTag == 0); 1992 STATIC_ASSERT(kSmiTag == 0);
1988 __ tst(code, Operand(kSmiTagMask)); 1993 __ JumpIfNotSmi(code, &slow);
1989 __ b(ne, &slow);
1990 1994
1991 // Convert the smi code to uint16. 1995 // Convert the smi code to uint16.
1992 __ and_(code, code, Operand(Smi::FromInt(0xffff))); 1996 __ and_(code, code, Operand(Smi::FromInt(0xffff)));
1993 1997
1994 StringCharFromCodeGenerator char_from_code_generator(code, r0); 1998 StringCharFromCodeGenerator char_from_code_generator(code, r0);
1995 char_from_code_generator.GenerateFast(masm()); 1999 char_from_code_generator.GenerateFast(masm());
1996 __ Drop(argc + 1); 2000 __ Drop(argc + 1);
1997 __ Ret(); 2001 __ Ret();
1998 2002
1999 StubRuntimeCallHelper call_helper; 2003 StubRuntimeCallHelper call_helper;
2000 char_from_code_generator.GenerateSlow(masm(), call_helper); 2004 char_from_code_generator.GenerateSlow(masm(), call_helper);
2001 2005
2002 // Tail call the full function. We do not have to patch the receiver 2006 // Tail call the full function. We do not have to patch the receiver
2003 // because the function makes no use of it. 2007 // because the function makes no use of it.
2004 __ bind(&slow); 2008 __ bind(&slow);
2005 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2009 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
2006 2010
2007 __ bind(&miss); 2011 __ bind(&miss);
2008 // r2: function name. 2012 // r2: function name.
2009 MaybeObject* maybe_result = GenerateMissBranch(); 2013 MaybeObject* maybe_result = GenerateMissBranch();
2010 if (maybe_result->IsFailure()) return maybe_result; 2014 if (maybe_result->IsFailure()) return maybe_result;
2011 2015
2012 // Return the generated code. 2016 // Return the generated code.
2013 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 2017 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
2014 } 2018 }
2015 2019
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
2143 __ Drop(argc + 1); 2147 __ Drop(argc + 1);
2144 __ Ret(); 2148 __ Ret();
2145 2149
2146 __ bind(&wont_fit_smi); 2150 __ bind(&wont_fit_smi);
2147 // Restore FPCSR and fall to slow case. 2151 // Restore FPCSR and fall to slow case.
2148 __ vmsr(r3); 2152 __ vmsr(r3);
2149 2153
2150 __ bind(&slow); 2154 __ bind(&slow);
2151 // Tail call the full function. We do not have to patch the receiver 2155 // Tail call the full function. We do not have to patch the receiver
2152 // because the function makes no use of it. 2156 // because the function makes no use of it.
2153 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2157 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
2154 2158
2155 __ bind(&miss); 2159 __ bind(&miss);
2156 // r2: function name. 2160 // r2: function name.
2157 MaybeObject* maybe_result = GenerateMissBranch(); 2161 MaybeObject* maybe_result = GenerateMissBranch();
2158 if (maybe_result->IsFailure()) return maybe_result; 2162 if (maybe_result->IsFailure()) return maybe_result;
2159 2163
2160 // Return the generated code. 2164 // Return the generated code.
2161 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 2165 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
2162 } 2166 }
2163 2167
(...skipping 17 matching lines...) Expand all
2181 // arguments, bail out to the regular call. 2185 // arguments, bail out to the regular call.
2182 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value(); 2186 if (!object->IsJSObject() || argc != 1) return heap()->undefined_value();
2183 2187
2184 Label miss; 2188 Label miss;
2185 GenerateNameCheck(name, &miss); 2189 GenerateNameCheck(name, &miss);
2186 2190
2187 if (cell == NULL) { 2191 if (cell == NULL) {
2188 __ ldr(r1, MemOperand(sp, 1 * kPointerSize)); 2192 __ ldr(r1, MemOperand(sp, 1 * kPointerSize));
2189 2193
2190 STATIC_ASSERT(kSmiTag == 0); 2194 STATIC_ASSERT(kSmiTag == 0);
2191 __ tst(r1, Operand(kSmiTagMask)); 2195 __ JumpIfSmi(r1, &miss);
2192 __ b(eq, &miss);
2193 2196
2194 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, 2197 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
2195 &miss); 2198 &miss);
2196 } else { 2199 } else {
2197 ASSERT(cell->value() == function); 2200 ASSERT(cell->value() == function);
2198 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss); 2201 GenerateGlobalReceiverCheck(JSObject::cast(object), holder, name, &miss);
2199 GenerateLoadFunctionFromCell(cell, function, &miss); 2202 GenerateLoadFunctionFromCell(cell, function, &miss);
2200 } 2203 }
2201 2204
2202 // Load the (only) argument into r0. 2205 // Load the (only) argument into r0.
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
2245 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 2248 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
2246 __ AllocateHeapNumber(r0, r4, r5, r6, &slow); 2249 __ AllocateHeapNumber(r0, r4, r5, r6, &slow);
2247 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 2250 __ str(r1, FieldMemOperand(r0, HeapNumber::kExponentOffset));
2248 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 2251 __ str(r3, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
2249 __ Drop(argc + 1); 2252 __ Drop(argc + 1);
2250 __ Ret(); 2253 __ Ret();
2251 2254
2252 // Tail call the full function. We do not have to patch the receiver 2255 // Tail call the full function. We do not have to patch the receiver
2253 // because the function makes no use of it. 2256 // because the function makes no use of it.
2254 __ bind(&slow); 2257 __ bind(&slow);
2255 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2258 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, CALL_AS_METHOD);
2256 2259
2257 __ bind(&miss); 2260 __ bind(&miss);
2258 // r2: function name. 2261 // r2: function name.
2259 MaybeObject* maybe_result = GenerateMissBranch(); 2262 MaybeObject* maybe_result = GenerateMissBranch();
2260 if (maybe_result->IsFailure()) return maybe_result; 2263 if (maybe_result->IsFailure()) return maybe_result;
2261 2264
2262 // Return the generated code. 2265 // Return the generated code.
2263 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name); 2266 return (cell == NULL) ? GetCode(function) : GetCode(NORMAL, name);
2264 } 2267 }
2265 2268
(...skipping 19 matching lines...) Expand all
2285 2288
2286 Label miss, miss_before_stack_reserved; 2289 Label miss, miss_before_stack_reserved;
2287 2290
2288 GenerateNameCheck(name, &miss_before_stack_reserved); 2291 GenerateNameCheck(name, &miss_before_stack_reserved);
2289 2292
2290 // Get the receiver from the stack. 2293 // Get the receiver from the stack.
2291 const int argc = arguments().immediate(); 2294 const int argc = arguments().immediate();
2292 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 2295 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2293 2296
2294 // Check that the receiver isn't a smi. 2297 // Check that the receiver isn't a smi.
2295 __ tst(r1, Operand(kSmiTagMask)); 2298 __ JumpIfSmi(r1, &miss_before_stack_reserved);
2296 __ b(eq, &miss_before_stack_reserved);
2297 2299
2298 __ IncrementCounter(counters->call_const(), 1, r0, r3); 2300 __ IncrementCounter(counters->call_const(), 1, r0, r3);
2299 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3); 2301 __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r3);
2300 2302
2301 ReserveSpaceForFastApiCall(masm(), r0); 2303 ReserveSpaceForFastApiCall(masm(), r0);
2302 2304
2303 // Check that the maps haven't changed and find a Holder as a side effect. 2305 // Check that the maps haven't changed and find a Holder as a side effect.
2304 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name, 2306 CheckPrototypes(JSObject::cast(object), r1, holder, r0, r3, r4, name,
2305 depth, &miss); 2307 depth, &miss);
2306 2308
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2340 Label miss; 2342 Label miss;
2341 2343
2342 GenerateNameCheck(name, &miss); 2344 GenerateNameCheck(name, &miss);
2343 2345
2344 // Get the receiver from the stack 2346 // Get the receiver from the stack
2345 const int argc = arguments().immediate(); 2347 const int argc = arguments().immediate();
2346 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 2348 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2347 2349
2348 // Check that the receiver isn't a smi. 2350 // Check that the receiver isn't a smi.
2349 if (check != NUMBER_CHECK) { 2351 if (check != NUMBER_CHECK) {
2350 __ tst(r1, Operand(kSmiTagMask)); 2352 __ JumpIfSmi(r1, &miss);
2351 __ b(eq, &miss);
2352 } 2353 }
2353 2354
2354 // Make sure that it's okay not to patch the on stack receiver 2355 // Make sure that it's okay not to patch the on stack receiver
2355 // unless we're doing a receiver map check. 2356 // unless we're doing a receiver map check.
2356 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2357 ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK);
2357 2358
2358 SharedFunctionInfo* function_info = function->shared(); 2359 SharedFunctionInfo* function_info = function->shared();
2359 switch (check) { 2360 switch (check) {
2360 case RECEIVER_MAP_CHECK: 2361 case RECEIVER_MAP_CHECK:
2361 __ IncrementCounter(masm()->isolate()->counters()->call_const(), 2362 __ IncrementCounter(masm()->isolate()->counters()->call_const(),
(...skipping 12 matching lines...) Expand all
2374 break; 2375 break;
2375 2376
2376 case STRING_CHECK: 2377 case STRING_CHECK:
2377 if (!function->IsBuiltin() && !function_info->strict_mode()) { 2378 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2378 // Calling non-strict non-builtins with a value as the receiver 2379 // Calling non-strict non-builtins with a value as the receiver
2379 // requires boxing. 2380 // requires boxing.
2380 __ jmp(&miss); 2381 __ jmp(&miss);
2381 } else { 2382 } else {
2382 // Check that the object is a two-byte string or a symbol. 2383 // Check that the object is a two-byte string or a symbol.
2383 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); 2384 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
2384 __ b(hs, &miss); 2385 __ b(ge, &miss);
2385 // Check that the maps starting from the prototype haven't changed. 2386 // Check that the maps starting from the prototype haven't changed.
2386 GenerateDirectLoadGlobalFunctionPrototype( 2387 GenerateDirectLoadGlobalFunctionPrototype(
2387 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); 2388 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
2388 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 2389 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
2389 r1, r4, name, &miss); 2390 r1, r4, name, &miss);
2390 } 2391 }
2391 break; 2392 break;
2392 2393
2393 case NUMBER_CHECK: { 2394 case NUMBER_CHECK: {
2394 if (!function->IsBuiltin() && !function_info->strict_mode()) { 2395 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2395 // Calling non-strict non-builtins with a value as the receiver 2396 // Calling non-strict non-builtins with a value as the receiver
2396 // requires boxing. 2397 // requires boxing.
2397 __ jmp(&miss); 2398 __ jmp(&miss);
2398 } else { 2399 } else {
2399 Label fast; 2400 Label fast;
2400 // Check that the object is a smi or a heap number. 2401 // Check that the object is a smi or a heap number.
2401 __ tst(r1, Operand(kSmiTagMask)); 2402 __ JumpIfSmi(r1, &fast);
2402 __ b(eq, &fast);
2403 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); 2403 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
2404 __ b(ne, &miss); 2404 __ b(ne, &miss);
2405 __ bind(&fast); 2405 __ bind(&fast);
2406 // Check that the maps starting from the prototype haven't changed. 2406 // Check that the maps starting from the prototype haven't changed.
2407 GenerateDirectLoadGlobalFunctionPrototype( 2407 GenerateDirectLoadGlobalFunctionPrototype(
2408 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); 2408 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
2409 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 2409 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
2410 r1, r4, name, &miss); 2410 r1, r4, name, &miss);
2411 } 2411 }
2412 break; 2412 break;
(...skipping 20 matching lines...) Expand all
2433 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 2433 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
2434 r1, r4, name, &miss); 2434 r1, r4, name, &miss);
2435 } 2435 }
2436 break; 2436 break;
2437 } 2437 }
2438 2438
2439 default: 2439 default:
2440 UNREACHABLE(); 2440 UNREACHABLE();
2441 } 2441 }
2442 2442
2443 __ InvokeFunction(function, arguments(), JUMP_FUNCTION); 2443 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
2444 ? CALL_AS_FUNCTION
2445 : CALL_AS_METHOD;
2446 __ InvokeFunction(function, arguments(), JUMP_FUNCTION, call_kind);
2444 2447
2445 // Handle call cache miss. 2448 // Handle call cache miss.
2446 __ bind(&miss); 2449 __ bind(&miss);
2447 MaybeObject* maybe_result = GenerateMissBranch(); 2450 MaybeObject* maybe_result = GenerateMissBranch();
2448 if (maybe_result->IsFailure()) return maybe_result; 2451 if (maybe_result->IsFailure()) return maybe_result;
2449 2452
2450 // Return the generated code. 2453 // Return the generated code.
2451 return GetCode(function); 2454 return GetCode(function);
2452 } 2455 }
2453 2456
(...skipping 12 matching lines...) Expand all
2466 2469
2467 // Get the number of arguments. 2470 // Get the number of arguments.
2468 const int argc = arguments().immediate(); 2471 const int argc = arguments().immediate();
2469 2472
2470 LookupResult lookup; 2473 LookupResult lookup;
2471 LookupPostInterceptor(holder, name, &lookup); 2474 LookupPostInterceptor(holder, name, &lookup);
2472 2475
2473 // Get the receiver from the stack. 2476 // Get the receiver from the stack.
2474 __ ldr(r1, MemOperand(sp, argc * kPointerSize)); 2477 __ ldr(r1, MemOperand(sp, argc * kPointerSize));
2475 2478
2476 CallInterceptorCompiler compiler(this, arguments(), r2); 2479 CallInterceptorCompiler compiler(this, arguments(), r2, extra_ic_state_);
2477 MaybeObject* result = compiler.Compile(masm(), 2480 MaybeObject* result = compiler.Compile(masm(),
2478 object, 2481 object,
2479 holder, 2482 holder,
2480 name, 2483 name,
2481 &lookup, 2484 &lookup,
2482 r1, 2485 r1,
2483 r3, 2486 r3,
2484 r4, 2487 r4,
2485 r0, 2488 r0,
2486 &miss); 2489 &miss);
2487 if (result->IsFailure()) { 2490 if (result->IsFailure()) {
2488 return result; 2491 return result;
2489 } 2492 }
2490 2493
2491 // Move returned value, the function to call, to r1. 2494 // Move returned value, the function to call, to r1.
2492 __ mov(r1, r0); 2495 __ mov(r1, r0);
2493 // Restore receiver. 2496 // Restore receiver.
2494 __ ldr(r0, MemOperand(sp, argc * kPointerSize)); 2497 __ ldr(r0, MemOperand(sp, argc * kPointerSize));
2495 2498
2496 GenerateCallFunction(masm(), object, arguments(), &miss); 2499 GenerateCallFunction(masm(), object, arguments(), &miss, extra_ic_state_);
2497 2500
2498 // Handle call cache miss. 2501 // Handle call cache miss.
2499 __ bind(&miss); 2502 __ bind(&miss);
2500 MaybeObject* maybe_result = GenerateMissBranch(); 2503 MaybeObject* maybe_result = GenerateMissBranch();
2501 if (maybe_result->IsFailure()) return maybe_result; 2504 if (maybe_result->IsFailure()) return maybe_result;
2502 2505
2503 // Return the generated code. 2506 // Return the generated code.
2504 return GetCode(INTERCEPTOR, name); 2507 return GetCode(INTERCEPTOR, name);
2505 } 2508 }
2506 2509
2507 2510
2508 MaybeObject* CallStubCompiler::CompileCallGlobal( 2511 MaybeObject* CallStubCompiler::CompileCallGlobal(JSObject* object,
2509 JSObject* object, 2512 GlobalObject* holder,
2510 GlobalObject* holder, 2513 JSGlobalPropertyCell* cell,
2511 JSGlobalPropertyCell* cell, 2514 JSFunction* function,
2512 JSFunction* function, 2515 String* name) {
2513 String* name,
2514 Code::ExtraICState extra_ic_state) {
2515 // ----------- S t a t e ------------- 2516 // ----------- S t a t e -------------
2516 // -- r2 : name 2517 // -- r2 : name
2517 // -- lr : return address 2518 // -- lr : return address
2518 // ----------------------------------- 2519 // -----------------------------------
2519 2520
2520 if (HasCustomCallGenerator(function)) { 2521 if (HasCustomCallGenerator(function)) {
2521 MaybeObject* maybe_result = CompileCustomCall( 2522 MaybeObject* maybe_result = CompileCustomCall(
2522 object, holder, cell, function, name); 2523 object, holder, cell, function, name);
2523 Object* result; 2524 Object* result;
2524 if (!maybe_result->ToObject(&result)) return maybe_result; 2525 if (!maybe_result->ToObject(&result)) return maybe_result;
(...skipping 21 matching lines...) Expand all
2546 2547
2547 // Setup the context (function already in r1). 2548 // Setup the context (function already in r1).
2548 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 2549 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
2549 2550
2550 // Jump to the cached code (tail call). 2551 // Jump to the cached code (tail call).
2551 Counters* counters = masm()->isolate()->counters(); 2552 Counters* counters = masm()->isolate()->counters();
2552 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4); 2553 __ IncrementCounter(counters->call_global_inline(), 1, r3, r4);
2553 ASSERT(function->is_compiled()); 2554 ASSERT(function->is_compiled());
2554 Handle<Code> code(function->code()); 2555 Handle<Code> code(function->code());
2555 ParameterCount expected(function->shared()->formal_parameter_count()); 2556 ParameterCount expected(function->shared()->formal_parameter_count());
2556 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) 2557 CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
2557 ? CALL_AS_FUNCTION 2558 ? CALL_AS_FUNCTION
2558 : CALL_AS_METHOD; 2559 : CALL_AS_METHOD;
2559 if (V8::UseCrankshaft()) { 2560 if (V8::UseCrankshaft()) {
2560 // TODO(kasperl): For now, we always call indirectly through the 2561 // TODO(kasperl): For now, we always call indirectly through the
2561 // code field in the function to allow recompilation to take effect 2562 // code field in the function to allow recompilation to take effect
2562 // without changing any of the call sites. 2563 // without changing any of the call sites.
2563 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); 2564 __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
2564 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION, 2565 __ InvokeCode(r3, expected, arguments(), JUMP_FUNCTION,
2565 NullCallWrapper(), call_kind); 2566 NullCallWrapper(), call_kind);
2566 } else { 2567 } else {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2611 String* name) { 2612 String* name) {
2612 // ----------- S t a t e ------------- 2613 // ----------- S t a t e -------------
2613 // -- r0 : value 2614 // -- r0 : value
2614 // -- r1 : receiver 2615 // -- r1 : receiver
2615 // -- r2 : name 2616 // -- r2 : name
2616 // -- lr : return address 2617 // -- lr : return address
2617 // ----------------------------------- 2618 // -----------------------------------
2618 Label miss; 2619 Label miss;
2619 2620
2620 // Check that the object isn't a smi. 2621 // Check that the object isn't a smi.
2621 __ tst(r1, Operand(kSmiTagMask)); 2622 __ JumpIfSmi(r1, &miss);
2622 __ b(eq, &miss);
2623 2623
2624 // Check that the map of the object hasn't changed. 2624 // Check that the map of the object hasn't changed.
2625 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 2625 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
2626 __ cmp(r3, Operand(Handle<Map>(object->map()))); 2626 __ cmp(r3, Operand(Handle<Map>(object->map())));
2627 __ b(ne, &miss); 2627 __ b(ne, &miss);
2628 2628
2629 // Perform global security token check if needed. 2629 // Perform global security token check if needed.
2630 if (object->IsJSGlobalProxy()) { 2630 if (object->IsJSGlobalProxy()) {
2631 __ CheckAccessGlobalProxy(r1, r3, &miss); 2631 __ CheckAccessGlobalProxy(r1, r3, &miss);
2632 } 2632 }
(...skipping 26 matching lines...) Expand all
2659 String* name) { 2659 String* name) {
2660 // ----------- S t a t e ------------- 2660 // ----------- S t a t e -------------
2661 // -- r0 : value 2661 // -- r0 : value
2662 // -- r1 : receiver 2662 // -- r1 : receiver
2663 // -- r2 : name 2663 // -- r2 : name
2664 // -- lr : return address 2664 // -- lr : return address
2665 // ----------------------------------- 2665 // -----------------------------------
2666 Label miss; 2666 Label miss;
2667 2667
2668 // Check that the object isn't a smi. 2668 // Check that the object isn't a smi.
2669 __ tst(r1, Operand(kSmiTagMask)); 2669 __ JumpIfSmi(r1, &miss);
2670 __ b(eq, &miss);
2671 2670
2672 // Check that the map of the object hasn't changed. 2671 // Check that the map of the object hasn't changed.
2673 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset)); 2672 __ ldr(r3, FieldMemOperand(r1, HeapObject::kMapOffset));
2674 __ cmp(r3, Operand(Handle<Map>(receiver->map()))); 2673 __ cmp(r3, Operand(Handle<Map>(receiver->map())));
2675 __ b(ne, &miss); 2674 __ b(ne, &miss);
2676 2675
2677 // Perform global security token check if needed. 2676 // Perform global security token check if needed.
2678 if (receiver->IsJSGlobalProxy()) { 2677 if (receiver->IsJSGlobalProxy()) {
2679 __ CheckAccessGlobalProxy(r1, r3, &miss); 2678 __ CheckAccessGlobalProxy(r1, r3, &miss);
2680 } 2679 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2751 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2750 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2752 JSObject* object, 2751 JSObject* object,
2753 JSObject* last) { 2752 JSObject* last) {
2754 // ----------- S t a t e ------------- 2753 // ----------- S t a t e -------------
2755 // -- r0 : receiver 2754 // -- r0 : receiver
2756 // -- lr : return address 2755 // -- lr : return address
2757 // ----------------------------------- 2756 // -----------------------------------
2758 Label miss; 2757 Label miss;
2759 2758
2760 // Check that receiver is not a smi. 2759 // Check that receiver is not a smi.
2761 __ tst(r0, Operand(kSmiTagMask)); 2760 __ JumpIfSmi(r0, &miss);
2762 __ b(eq, &miss);
2763 2761
2764 // Check the maps of the full prototype chain. 2762 // Check the maps of the full prototype chain.
2765 CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss); 2763 CheckPrototypes(object, r0, last, r3, r1, r4, name, &miss);
2766 2764
2767 // If the last object in the prototype chain is a global object, 2765 // If the last object in the prototype chain is a global object,
2768 // check that the global property cell is empty. 2766 // check that the global property cell is empty.
2769 if (last->IsGlobalObject()) { 2767 if (last->IsGlobalObject()) {
2770 MaybeObject* cell = GenerateCheckPropertyCell(masm(), 2768 MaybeObject* cell = GenerateCheckPropertyCell(masm(),
2771 GlobalObject::cast(last), 2769 GlobalObject::cast(last),
2772 name, 2770 name,
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
2896 // -- r0 : receiver 2894 // -- r0 : receiver
2897 // -- r2 : name 2895 // -- r2 : name
2898 // -- lr : return address 2896 // -- lr : return address
2899 // ----------------------------------- 2897 // -----------------------------------
2900 Label miss; 2898 Label miss;
2901 2899
2902 // If the object is the holder then we know that it's a global 2900 // If the object is the holder then we know that it's a global
2903 // object which can only happen for contextual calls. In this case, 2901 // object which can only happen for contextual calls. In this case,
2904 // the receiver cannot be a smi. 2902 // the receiver cannot be a smi.
2905 if (object != holder) { 2903 if (object != holder) {
2906 __ tst(r0, Operand(kSmiTagMask)); 2904 __ JumpIfSmi(r0, &miss);
2907 __ b(eq, &miss);
2908 } 2905 }
2909 2906
2910 // Check that the map of the global has not changed. 2907 // Check that the map of the global has not changed.
2911 CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss); 2908 CheckPrototypes(object, r0, holder, r3, r4, r1, name, &miss);
2912 2909
2913 // Get the value from the cell. 2910 // Get the value from the cell.
2914 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell))); 2911 __ mov(r3, Operand(Handle<JSGlobalPropertyCell>(cell)));
2915 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset)); 2912 __ ldr(r4, FieldMemOperand(r3, JSGlobalPropertyCell::kValueOffset));
2916 2913
2917 // Check for deleted property if property can actually be deleted. 2914 // Check for deleted property if property can actually be deleted.
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
3107 3104
3108 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); 3105 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
3109 __ bind(&miss); 3106 __ bind(&miss);
3110 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); 3107 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
3111 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3108 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3112 3109
3113 return GetCode(CALLBACKS, name); 3110 return GetCode(CALLBACKS, name);
3114 } 3111 }
3115 3112
3116 3113
3117 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) { 3114 MaybeObject* KeyedLoadStubCompiler::CompileLoadElement(Map* receiver_map) {
3118 // ----------- S t a t e ------------- 3115 // ----------- S t a t e -------------
3119 // -- lr : return address 3116 // -- lr : return address
3120 // -- r0 : key 3117 // -- r0 : key
3121 // -- r1 : receiver 3118 // -- r1 : receiver
3122 // ----------------------------------- 3119 // -----------------------------------
3123 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
3124 Code* stub; 3120 Code* stub;
3121 JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
3122 MaybeObject* maybe_stub = KeyedLoadElementStub(elements_kind).TryGetCode();
3125 if (!maybe_stub->To(&stub)) return maybe_stub; 3123 if (!maybe_stub->To(&stub)) return maybe_stub;
3126 __ DispatchMap(r1, 3124 __ DispatchMap(r1,
3127 r2, 3125 r2,
3128 Handle<Map>(receiver_map), 3126 Handle<Map>(receiver_map),
3129 Handle<Code>(stub), 3127 Handle<Code>(stub),
3130 DO_SMI_CHECK); 3128 DO_SMI_CHECK);
3131 3129
3132 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); 3130 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3133 __ Jump(ic, RelocInfo::CODE_TARGET); 3131 __ Jump(ic, RelocInfo::CODE_TARGET);
3134 3132
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3198 3196
3199 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); 3197 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
3200 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); 3198 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3201 __ Jump(ic, RelocInfo::CODE_TARGET); 3199 __ Jump(ic, RelocInfo::CODE_TARGET);
3202 3200
3203 // Return the generated code. 3201 // Return the generated code.
3204 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 3202 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
3205 } 3203 }
3206 3204
3207 3205
3208 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement( 3206 MaybeObject* KeyedStoreStubCompiler::CompileStoreElement(Map* receiver_map) {
3209 Map* receiver_map) {
3210 // ----------- S t a t e ------------- 3207 // ----------- S t a t e -------------
3211 // -- r0 : value 3208 // -- r0 : value
3212 // -- r1 : key 3209 // -- r1 : key
3213 // -- r2 : receiver 3210 // -- r2 : receiver
3214 // -- lr : return address 3211 // -- lr : return address
3215 // -- r3 : scratch 3212 // -- r3 : scratch
3216 // ----------------------------------- 3213 // -----------------------------------
3214 Code* stub;
3215 JSObject::ElementsKind elements_kind = receiver_map->elements_kind();
3217 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 3216 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
3218 MaybeObject* maybe_stub = 3217 MaybeObject* maybe_stub =
3219 KeyedStoreFastElementStub(is_js_array).TryGetCode(); 3218 KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode();
3220 Code* stub;
3221 if (!maybe_stub->To(&stub)) return maybe_stub; 3219 if (!maybe_stub->To(&stub)) return maybe_stub;
3222 __ DispatchMap(r2, 3220 __ DispatchMap(r2,
3223 r3, 3221 r3,
3224 Handle<Map>(receiver_map), 3222 Handle<Map>(receiver_map),
3225 Handle<Code>(stub), 3223 Handle<Code>(stub),
3226 DO_SMI_CHECK); 3224 DO_SMI_CHECK);
3227 3225
3228 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3226 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3229 __ Jump(ic, RelocInfo::CODE_TARGET); 3227 __ Jump(ic, RelocInfo::CODE_TARGET);
3230 3228
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
3284 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); 3282 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
3285 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset)); 3283 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kDebugInfoOffset));
3286 __ cmp(r2, r7); 3284 __ cmp(r2, r7);
3287 __ b(ne, &generic_stub_call); 3285 __ b(ne, &generic_stub_call);
3288 #endif 3286 #endif
3289 3287
3290 // Load the initial map and verify that it is in fact a map. 3288 // Load the initial map and verify that it is in fact a map.
3291 // r1: constructor function 3289 // r1: constructor function
3292 // r7: undefined 3290 // r7: undefined
3293 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); 3291 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset));
3294 __ tst(r2, Operand(kSmiTagMask)); 3292 __ JumpIfSmi(r2, &generic_stub_call);
3295 __ b(eq, &generic_stub_call);
3296 __ CompareObjectType(r2, r3, r4, MAP_TYPE); 3293 __ CompareObjectType(r2, r3, r4, MAP_TYPE);
3297 __ b(ne, &generic_stub_call); 3294 __ b(ne, &generic_stub_call);
3298 3295
3299 #ifdef DEBUG 3296 #ifdef DEBUG
3300 // Cannot construct functions this way. 3297 // Cannot construct functions this way.
3301 // r0: argc 3298 // r0: argc
3302 // r1: constructor function 3299 // r1: constructor function
3303 // r2: initial map 3300 // r2: initial map
3304 // r7: undefined 3301 // r7: undefined
3305 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); 3302 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
3402 // construction. 3399 // construction.
3403 __ bind(&generic_stub_call); 3400 __ bind(&generic_stub_call);
3404 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric(); 3401 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric();
3405 __ Jump(code, RelocInfo::CODE_TARGET); 3402 __ Jump(code, RelocInfo::CODE_TARGET);
3406 3403
3407 // Return the generated code. 3404 // Return the generated code.
3408 return GetCode(); 3405 return GetCode();
3409 } 3406 }
3410 3407
3411 3408
3412 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3413 JSObject*receiver, ExternalArrayType array_type) {
3414 // ----------- S t a t e -------------
3415 // -- lr : return address
3416 // -- r0 : key
3417 // -- r1 : receiver
3418 // -----------------------------------
3419 MaybeObject* maybe_stub =
3420 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3421 Code* stub;
3422 if (!maybe_stub->To(&stub)) return maybe_stub;
3423 __ DispatchMap(r1,
3424 r2,
3425 Handle<Map>(receiver->map()),
3426 Handle<Code>(stub),
3427 DO_SMI_CHECK);
3428
3429 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3430 __ Jump(ic, RelocInfo::CODE_TARGET);
3431
3432 // Return the generated code.
3433 return GetCode();
3434 }
3435
3436
3437 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3438 JSObject* receiver, ExternalArrayType array_type) {
3439 // ----------- S t a t e -------------
3440 // -- r0 : value
3441 // -- r1 : name
3442 // -- r2 : receiver
3443 // -- lr : return address
3444 // -----------------------------------
3445 MaybeObject* maybe_stub =
3446 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3447 Code* stub;
3448 if (!maybe_stub->To(&stub)) return maybe_stub;
3449 __ DispatchMap(r2,
3450 r3,
3451 Handle<Map>(receiver->map()),
3452 Handle<Code>(stub),
3453 DO_SMI_CHECK);
3454
3455 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3456 __ Jump(ic, RelocInfo::CODE_TARGET);
3457
3458 return GetCode();
3459 }
3460
3461
3462 #undef __ 3409 #undef __
3463 #define __ ACCESS_MASM(masm) 3410 #define __ ACCESS_MASM(masm)
3464 3411
3465 3412
3466 static bool IsElementTypeSigned(ExternalArrayType array_type) { 3413 void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
3467 switch (array_type) { 3414 MacroAssembler* masm) {
3468 case kExternalByteArray: 3415 // ---------- S t a t e --------------
3469 case kExternalShortArray: 3416 // -- lr : return address
3470 case kExternalIntArray: 3417 // -- r0 : key
3418 // -- r1 : receiver
3419 // -----------------------------------
3420 Label slow, miss_force_generic;
3421
3422 Register key = r0;
3423 Register receiver = r1;
3424
3425 __ JumpIfNotSmi(key, &miss_force_generic);
3426 __ mov(r2, Operand(key, ASR, kSmiTagSize));
3427 __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset));
3428 __ LoadFromNumberDictionary(&slow, r4, key, r0, r2, r3, r5);
3429 __ Ret();
3430
3431 __ bind(&slow);
3432 __ IncrementCounter(
3433 masm->isolate()->counters()->keyed_load_external_array_slow(),
3434 1, r2, r3);
3435
3436 // ---------- S t a t e --------------
3437 // -- lr : return address
3438 // -- r0 : key
3439 // -- r1 : receiver
3440 // -----------------------------------
3441 Handle<Code> slow_ic =
3442 masm->isolate()->builtins()->KeyedLoadIC_Slow();
3443 __ Jump(slow_ic, RelocInfo::CODE_TARGET);
3444
3445 // Miss case, call the runtime.
3446 __ bind(&miss_force_generic);
3447
3448 // ---------- S t a t e --------------
3449 // -- lr : return address
3450 // -- r0 : key
3451 // -- r1 : receiver
3452 // -----------------------------------
3453
3454 Handle<Code> miss_ic =
3455 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3456 __ Jump(miss_ic, RelocInfo::CODE_TARGET);
3457 }
3458
3459
3460 static bool IsElementTypeSigned(JSObject::ElementsKind elements_kind) {
3461 switch (elements_kind) {
3462 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3463 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3464 case JSObject::EXTERNAL_INT_ELEMENTS:
3471 return true; 3465 return true;
3472 3466
3473 case kExternalUnsignedByteArray: 3467 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3474 case kExternalUnsignedShortArray: 3468 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3475 case kExternalUnsignedIntArray: 3469 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3470 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3476 return false; 3471 return false;
3477 3472
3478 default: 3473 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3474 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3475 case JSObject::FAST_ELEMENTS:
3476 case JSObject::FAST_DOUBLE_ELEMENTS:
3477 case JSObject::DICTIONARY_ELEMENTS:
3478 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3479 UNREACHABLE(); 3479 UNREACHABLE();
3480 return false; 3480 return false;
3481 } 3481 }
3482 return false;
3482 } 3483 }
3483 3484
3484 3485
3485 void KeyedLoadStubCompiler::GenerateLoadExternalArray( 3486 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3486 MacroAssembler* masm, 3487 MacroAssembler* masm,
3487 ExternalArrayType array_type) { 3488 JSObject::ElementsKind elements_kind) {
3488 // ---------- S t a t e -------------- 3489 // ---------- S t a t e --------------
3489 // -- lr : return address 3490 // -- lr : return address
3490 // -- r0 : key 3491 // -- r0 : key
3491 // -- r1 : receiver 3492 // -- r1 : receiver
3492 // ----------------------------------- 3493 // -----------------------------------
3493 Label miss_force_generic, slow, failed_allocation; 3494 Label miss_force_generic, slow, failed_allocation;
3494 3495
3495 Register key = r0; 3496 Register key = r0;
3496 Register receiver = r1; 3497 Register receiver = r1;
3497 3498
(...skipping 13 matching lines...) Expand all
3511 __ b(lo, &miss_force_generic); 3512 __ b(lo, &miss_force_generic);
3512 3513
3513 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3514 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3514 // r3: base pointer of external storage 3515 // r3: base pointer of external storage
3515 3516
3516 // We are not untagging smi key and instead work with it 3517 // We are not untagging smi key and instead work with it
3517 // as if it was premultiplied by 2. 3518 // as if it was premultiplied by 2.
3518 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 3519 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
3519 3520
3520 Register value = r2; 3521 Register value = r2;
3521 switch (array_type) { 3522 switch (elements_kind) {
3522 case kExternalByteArray: 3523 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3523 __ ldrsb(value, MemOperand(r3, key, LSR, 1)); 3524 __ ldrsb(value, MemOperand(r3, key, LSR, 1));
3524 break; 3525 break;
3525 case kExternalPixelArray: 3526 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3526 case kExternalUnsignedByteArray: 3527 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3527 __ ldrb(value, MemOperand(r3, key, LSR, 1)); 3528 __ ldrb(value, MemOperand(r3, key, LSR, 1));
3528 break; 3529 break;
3529 case kExternalShortArray: 3530 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3530 __ ldrsh(value, MemOperand(r3, key, LSL, 0)); 3531 __ ldrsh(value, MemOperand(r3, key, LSL, 0));
3531 break; 3532 break;
3532 case kExternalUnsignedShortArray: 3533 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3533 __ ldrh(value, MemOperand(r3, key, LSL, 0)); 3534 __ ldrh(value, MemOperand(r3, key, LSL, 0));
3534 break; 3535 break;
3535 case kExternalIntArray: 3536 case JSObject::EXTERNAL_INT_ELEMENTS:
3536 case kExternalUnsignedIntArray: 3537 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3537 __ ldr(value, MemOperand(r3, key, LSL, 1)); 3538 __ ldr(value, MemOperand(r3, key, LSL, 1));
3538 break; 3539 break;
3539 case kExternalFloatArray: 3540 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3540 if (CpuFeatures::IsSupported(VFP3)) { 3541 if (CpuFeatures::IsSupported(VFP3)) {
3541 CpuFeatures::Scope scope(VFP3); 3542 CpuFeatures::Scope scope(VFP3);
3542 __ add(r2, r3, Operand(key, LSL, 1)); 3543 __ add(r2, r3, Operand(key, LSL, 1));
3543 __ vldr(s0, r2, 0); 3544 __ vldr(s0, r2, 0);
3544 } else { 3545 } else {
3545 __ ldr(value, MemOperand(r3, key, LSL, 1)); 3546 __ ldr(value, MemOperand(r3, key, LSL, 1));
3546 } 3547 }
3547 break; 3548 break;
3548 case kExternalDoubleArray: 3549 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3549 if (CpuFeatures::IsSupported(VFP3)) { 3550 if (CpuFeatures::IsSupported(VFP3)) {
3550 CpuFeatures::Scope scope(VFP3); 3551 CpuFeatures::Scope scope(VFP3);
3551 __ add(r2, r3, Operand(key, LSL, 2)); 3552 __ add(r2, r3, Operand(key, LSL, 2));
3552 __ vldr(d0, r2, 0); 3553 __ vldr(d0, r2, 0);
3553 } else { 3554 } else {
3554 __ add(r4, r3, Operand(key, LSL, 2)); 3555 __ add(r4, r3, Operand(key, LSL, 2));
3555 // r4: pointer to the beginning of the double we want to load. 3556 // r4: pointer to the beginning of the double we want to load.
3556 __ ldr(r2, MemOperand(r4, 0)); 3557 __ ldr(r2, MemOperand(r4, 0));
3557 __ ldr(r3, MemOperand(r4, Register::kSizeInBytes)); 3558 __ ldr(r3, MemOperand(r4, Register::kSizeInBytes));
3558 } 3559 }
3559 break; 3560 break;
3560 default: 3561 case JSObject::FAST_ELEMENTS:
3562 case JSObject::FAST_DOUBLE_ELEMENTS:
3563 case JSObject::DICTIONARY_ELEMENTS:
3564 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3561 UNREACHABLE(); 3565 UNREACHABLE();
3562 break; 3566 break;
3563 } 3567 }
3564 3568
3565 // For integer array types: 3569 // For integer array types:
3566 // r2: value 3570 // r2: value
3567 // For float array type: 3571 // For float array type:
3568 // s0: value (if VFP3 is supported) 3572 // s0: value (if VFP3 is supported)
3569 // r2: value (if VFP3 is not supported) 3573 // r2: value (if VFP3 is not supported)
3570 // For double array type: 3574 // For double array type:
3571 // d0: value (if VFP3 is supported) 3575 // d0: value (if VFP3 is supported)
3572 // r2/r3: value (if VFP3 is not supported) 3576 // r2/r3: value (if VFP3 is not supported)
3573 3577
3574 if (array_type == kExternalIntArray) { 3578 if (elements_kind == JSObject::EXTERNAL_INT_ELEMENTS) {
3575 // For the Int and UnsignedInt array types, we need to see whether 3579 // For the Int and UnsignedInt array types, we need to see whether
3576 // the value can be represented in a Smi. If not, we need to convert 3580 // the value can be represented in a Smi. If not, we need to convert
3577 // it to a HeapNumber. 3581 // it to a HeapNumber.
3578 Label box_int; 3582 Label box_int;
3579 __ cmp(value, Operand(0xC0000000)); 3583 __ cmp(value, Operand(0xC0000000));
3580 __ b(mi, &box_int); 3584 __ b(mi, &box_int);
3581 // Tag integer as smi and return it. 3585 // Tag integer as smi and return it.
3582 __ mov(r0, Operand(value, LSL, kSmiTagSize)); 3586 __ mov(r0, Operand(value, LSL, kSmiTagSize));
3583 __ Ret(); 3587 __ Ret();
3584 3588
(...skipping 23 matching lines...) Expand all
3608 dest, 3612 dest,
3609 d0, 3613 d0,
3610 dst1, 3614 dst1,
3611 dst2, 3615 dst2,
3612 r9, 3616 r9,
3613 s0); 3617 s0);
3614 __ str(dst1, FieldMemOperand(r0, HeapNumber::kMantissaOffset)); 3618 __ str(dst1, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
3615 __ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset)); 3619 __ str(dst2, FieldMemOperand(r0, HeapNumber::kExponentOffset));
3616 __ Ret(); 3620 __ Ret();
3617 } 3621 }
3618 } else if (array_type == kExternalUnsignedIntArray) { 3622 } else if (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) {
3619 // The test is different for unsigned int values. Since we need 3623 // The test is different for unsigned int values. Since we need
3620 // the value to be in the range of a positive smi, we can't 3624 // the value to be in the range of a positive smi, we can't
3621 // handle either of the top two bits being set in the value. 3625 // handle either of the top two bits being set in the value.
3622 if (CpuFeatures::IsSupported(VFP3)) { 3626 if (CpuFeatures::IsSupported(VFP3)) {
3623 CpuFeatures::Scope scope(VFP3); 3627 CpuFeatures::Scope scope(VFP3);
3624 Label box_int, done; 3628 Label box_int, done;
3625 __ tst(value, Operand(0xC0000000)); 3629 __ tst(value, Operand(0xC0000000));
3626 __ b(ne, &box_int); 3630 __ b(ne, &box_int);
3627 // Tag integer as smi and return it. 3631 // Tag integer as smi and return it.
3628 __ mov(r0, Operand(value, LSL, kSmiTagSize)); 3632 __ mov(r0, Operand(value, LSL, kSmiTagSize));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
3673 // space. 3677 // space.
3674 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3678 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
3675 __ AllocateHeapNumber(r4, r5, r7, r6, &slow); 3679 __ AllocateHeapNumber(r4, r5, r7, r6, &slow);
3676 3680
3677 __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset)); 3681 __ str(hiword, FieldMemOperand(r4, HeapNumber::kExponentOffset));
3678 __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset)); 3682 __ str(loword, FieldMemOperand(r4, HeapNumber::kMantissaOffset));
3679 3683
3680 __ mov(r0, r4); 3684 __ mov(r0, r4);
3681 __ Ret(); 3685 __ Ret();
3682 } 3686 }
3683 } else if (array_type == kExternalFloatArray) { 3687 } else if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
3684 // For the floating-point array type, we need to always allocate a 3688 // For the floating-point array type, we need to always allocate a
3685 // HeapNumber. 3689 // HeapNumber.
3686 if (CpuFeatures::IsSupported(VFP3)) { 3690 if (CpuFeatures::IsSupported(VFP3)) {
3687 CpuFeatures::Scope scope(VFP3); 3691 CpuFeatures::Scope scope(VFP3);
3688 // Allocate a HeapNumber for the result. Don't use r0 and r1 as 3692 // Allocate a HeapNumber for the result. Don't use r0 and r1 as
3689 // AllocateHeapNumber clobbers all registers - also when jumping due to 3693 // AllocateHeapNumber clobbers all registers - also when jumping due to
3690 // exhausted young space. 3694 // exhausted young space.
3691 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3695 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
3692 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); 3696 __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
3693 __ vcvt_f64_f32(d0, s0); 3697 __ vcvt_f64_f32(d0, s0);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
3743 3747
3744 __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord)); 3748 __ orr(r2, r2, Operand(r0, LSR, kMantissaShiftForHiWord));
3745 __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord)); 3749 __ mov(r0, Operand(r0, LSL, kMantissaShiftForLoWord));
3746 3750
3747 __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset)); 3751 __ str(r2, FieldMemOperand(r3, HeapNumber::kExponentOffset));
3748 __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset)); 3752 __ str(r0, FieldMemOperand(r3, HeapNumber::kMantissaOffset));
3749 3753
3750 __ mov(r0, r3); 3754 __ mov(r0, r3);
3751 __ Ret(); 3755 __ Ret();
3752 } 3756 }
3753 } else if (array_type == kExternalDoubleArray) { 3757 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
3754 if (CpuFeatures::IsSupported(VFP3)) { 3758 if (CpuFeatures::IsSupported(VFP3)) {
3755 CpuFeatures::Scope scope(VFP3); 3759 CpuFeatures::Scope scope(VFP3);
3756 // Allocate a HeapNumber for the result. Don't use r0 and r1 as 3760 // Allocate a HeapNumber for the result. Don't use r0 and r1 as
3757 // AllocateHeapNumber clobbers all registers - also when jumping due to 3761 // AllocateHeapNumber clobbers all registers - also when jumping due to
3758 // exhausted young space. 3762 // exhausted young space.
3759 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3763 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
3760 __ AllocateHeapNumber(r2, r3, r4, r6, &slow); 3764 __ AllocateHeapNumber(r2, r3, r4, r6, &slow);
3761 __ sub(r1, r2, Operand(kHeapObjectTag)); 3765 __ sub(r1, r2, Operand(kHeapObjectTag));
3762 __ vstr(d0, r1, HeapNumber::kValueOffset); 3766 __ vstr(d0, r1, HeapNumber::kValueOffset);
3763 3767
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3800 3804
3801 __ bind(&miss_force_generic); 3805 __ bind(&miss_force_generic);
3802 Code* stub = masm->isolate()->builtins()->builtin( 3806 Code* stub = masm->isolate()->builtins()->builtin(
3803 Builtins::kKeyedLoadIC_MissForceGeneric); 3807 Builtins::kKeyedLoadIC_MissForceGeneric);
3804 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET); 3808 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
3805 } 3809 }
3806 3810
3807 3811
3808 void KeyedStoreStubCompiler::GenerateStoreExternalArray( 3812 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3809 MacroAssembler* masm, 3813 MacroAssembler* masm,
3810 ExternalArrayType array_type) { 3814 JSObject::ElementsKind elements_kind) {
3811 // ---------- S t a t e -------------- 3815 // ---------- S t a t e --------------
3812 // -- r0 : value 3816 // -- r0 : value
3813 // -- r1 : key 3817 // -- r1 : key
3814 // -- r2 : receiver 3818 // -- r2 : receiver
3815 // -- lr : return address 3819 // -- lr : return address
3816 // ----------------------------------- 3820 // -----------------------------------
3817 Label slow, check_heap_number, miss_force_generic; 3821 Label slow, check_heap_number, miss_force_generic;
3818 3822
3819 // Register usage. 3823 // Register usage.
3820 Register value = r0; 3824 Register value = r0;
(...skipping 13 matching lines...) Expand all
3834 __ SmiUntag(r4, key); 3838 __ SmiUntag(r4, key);
3835 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 3839 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
3836 __ cmp(r4, ip); 3840 __ cmp(r4, ip);
3837 // Unsigned comparison catches both negative and too-large values. 3841 // Unsigned comparison catches both negative and too-large values.
3838 __ b(hs, &miss_force_generic); 3842 __ b(hs, &miss_force_generic);
3839 3843
3840 // Handle both smis and HeapNumbers in the fast path. Go to the 3844 // Handle both smis and HeapNumbers in the fast path. Go to the
3841 // runtime for all other kinds of values. 3845 // runtime for all other kinds of values.
3842 // r3: external array. 3846 // r3: external array.
3843 // r4: key (integer). 3847 // r4: key (integer).
3844 if (array_type == kExternalPixelArray) { 3848 if (elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS) {
3845 // Double to pixel conversion is only implemented in the runtime for now. 3849 // Double to pixel conversion is only implemented in the runtime for now.
3846 __ JumpIfNotSmi(value, &slow); 3850 __ JumpIfNotSmi(value, &slow);
3847 } else { 3851 } else {
3848 __ JumpIfNotSmi(value, &check_heap_number); 3852 __ JumpIfNotSmi(value, &check_heap_number);
3849 } 3853 }
3850 __ SmiUntag(r5, value); 3854 __ SmiUntag(r5, value);
3851 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3855 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3852 3856
3853 // r3: base pointer of external storage. 3857 // r3: base pointer of external storage.
3854 // r4: key (integer). 3858 // r4: key (integer).
3855 // r5: value (integer). 3859 // r5: value (integer).
3856 switch (array_type) { 3860 switch (elements_kind) {
3857 case kExternalPixelArray: 3861 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3858 // Clamp the value to [0..255]. 3862 // Clamp the value to [0..255].
3859 __ Usat(r5, 8, Operand(r5)); 3863 __ Usat(r5, 8, Operand(r5));
3860 __ strb(r5, MemOperand(r3, r4, LSL, 0)); 3864 __ strb(r5, MemOperand(r3, r4, LSL, 0));
3861 break; 3865 break;
3862 case kExternalByteArray: 3866 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3863 case kExternalUnsignedByteArray: 3867 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3864 __ strb(r5, MemOperand(r3, r4, LSL, 0)); 3868 __ strb(r5, MemOperand(r3, r4, LSL, 0));
3865 break; 3869 break;
3866 case kExternalShortArray: 3870 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3867 case kExternalUnsignedShortArray: 3871 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3868 __ strh(r5, MemOperand(r3, r4, LSL, 1)); 3872 __ strh(r5, MemOperand(r3, r4, LSL, 1));
3869 break; 3873 break;
3870 case kExternalIntArray: 3874 case JSObject::EXTERNAL_INT_ELEMENTS:
3871 case kExternalUnsignedIntArray: 3875 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3872 __ str(r5, MemOperand(r3, r4, LSL, 2)); 3876 __ str(r5, MemOperand(r3, r4, LSL, 2));
3873 break; 3877 break;
3874 case kExternalFloatArray: 3878 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3875 // Perform int-to-float conversion and store to memory. 3879 // Perform int-to-float conversion and store to memory.
3876 StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9); 3880 StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
3877 break; 3881 break;
3878 case kExternalDoubleArray: 3882 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3879 __ add(r3, r3, Operand(r4, LSL, 3)); 3883 __ add(r3, r3, Operand(r4, LSL, 3));
3880 // r3: effective address of the double element 3884 // r3: effective address of the double element
3881 FloatingPointHelper::Destination destination; 3885 FloatingPointHelper::Destination destination;
3882 if (CpuFeatures::IsSupported(VFP3)) { 3886 if (CpuFeatures::IsSupported(VFP3)) {
3883 destination = FloatingPointHelper::kVFPRegisters; 3887 destination = FloatingPointHelper::kVFPRegisters;
3884 } else { 3888 } else {
3885 destination = FloatingPointHelper::kCoreRegisters; 3889 destination = FloatingPointHelper::kCoreRegisters;
3886 } 3890 }
3887 FloatingPointHelper::ConvertIntToDouble( 3891 FloatingPointHelper::ConvertIntToDouble(
3888 masm, r5, destination, 3892 masm, r5, destination,
3889 d0, r6, r7, // These are: double_dst, dst1, dst2. 3893 d0, r6, r7, // These are: double_dst, dst1, dst2.
3890 r4, s2); // These are: scratch2, single_scratch. 3894 r4, s2); // These are: scratch2, single_scratch.
3891 if (destination == FloatingPointHelper::kVFPRegisters) { 3895 if (destination == FloatingPointHelper::kVFPRegisters) {
3892 CpuFeatures::Scope scope(VFP3); 3896 CpuFeatures::Scope scope(VFP3);
3893 __ vstr(d0, r3, 0); 3897 __ vstr(d0, r3, 0);
3894 } else { 3898 } else {
3895 __ str(r6, MemOperand(r3, 0)); 3899 __ str(r6, MemOperand(r3, 0));
3896 __ str(r7, MemOperand(r3, Register::kSizeInBytes)); 3900 __ str(r7, MemOperand(r3, Register::kSizeInBytes));
3897 } 3901 }
3898 break; 3902 break;
3899 default: 3903 case JSObject::FAST_ELEMENTS:
3904 case JSObject::FAST_DOUBLE_ELEMENTS:
3905 case JSObject::DICTIONARY_ELEMENTS:
3906 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3900 UNREACHABLE(); 3907 UNREACHABLE();
3901 break; 3908 break;
3902 } 3909 }
3903 3910
3904 // Entry registers are intact, r0 holds the value which is the return value. 3911 // Entry registers are intact, r0 holds the value which is the return value.
3905 __ Ret(); 3912 __ Ret();
3906 3913
3907 if (array_type != kExternalPixelArray) { 3914 if (elements_kind != JSObject::EXTERNAL_PIXEL_ELEMENTS) {
3908 // r3: external array. 3915 // r3: external array.
3909 // r4: index (integer). 3916 // r4: index (integer).
3910 __ bind(&check_heap_number); 3917 __ bind(&check_heap_number);
3911 __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); 3918 __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE);
3912 __ b(ne, &slow); 3919 __ b(ne, &slow);
3913 3920
3914 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3921 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3915 3922
3916 // r3: base pointer of external storage. 3923 // r3: base pointer of external storage.
3917 // r4: key (integer). 3924 // r4: key (integer).
3918 3925
3919 // The WebGL specification leaves the behavior of storing NaN and 3926 // The WebGL specification leaves the behavior of storing NaN and
3920 // +/-Infinity into integer arrays basically undefined. For more 3927 // +/-Infinity into integer arrays basically undefined. For more
3921 // reproducible behavior, convert these to zero. 3928 // reproducible behavior, convert these to zero.
3922 if (CpuFeatures::IsSupported(VFP3)) { 3929 if (CpuFeatures::IsSupported(VFP3)) {
3923 CpuFeatures::Scope scope(VFP3); 3930 CpuFeatures::Scope scope(VFP3);
3924 3931
3925 if (array_type == kExternalFloatArray) { 3932 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
3926 // vldr requires offset to be a multiple of 4 so we can not 3933 // vldr requires offset to be a multiple of 4 so we can not
3927 // include -kHeapObjectTag into it. 3934 // include -kHeapObjectTag into it.
3928 __ sub(r5, r0, Operand(kHeapObjectTag)); 3935 __ sub(r5, r0, Operand(kHeapObjectTag));
3929 __ vldr(d0, r5, HeapNumber::kValueOffset); 3936 __ vldr(d0, r5, HeapNumber::kValueOffset);
3930 __ add(r5, r3, Operand(r4, LSL, 2)); 3937 __ add(r5, r3, Operand(r4, LSL, 2));
3931 __ vcvt_f32_f64(s0, d0); 3938 __ vcvt_f32_f64(s0, d0);
3932 __ vstr(s0, r5, 0); 3939 __ vstr(s0, r5, 0);
3933 } else if (array_type == kExternalDoubleArray) { 3940 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
3934 __ sub(r5, r0, Operand(kHeapObjectTag)); 3941 __ sub(r5, r0, Operand(kHeapObjectTag));
3935 __ vldr(d0, r5, HeapNumber::kValueOffset); 3942 __ vldr(d0, r5, HeapNumber::kValueOffset);
3936 __ add(r5, r3, Operand(r4, LSL, 3)); 3943 __ add(r5, r3, Operand(r4, LSL, 3));
3937 __ vstr(d0, r5, 0); 3944 __ vstr(d0, r5, 0);
3938 } else { 3945 } else {
3939 // Need to perform float-to-int conversion.
3940 // Test for NaN or infinity (both give zero).
3941 __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset));
3942
3943 // Hoisted load. vldr requires offset to be a multiple of 4 so we can 3946 // Hoisted load. vldr requires offset to be a multiple of 4 so we can
3944 // not include -kHeapObjectTag into it. 3947 // not include -kHeapObjectTag into it.
3945 __ sub(r5, value, Operand(kHeapObjectTag)); 3948 __ sub(r5, value, Operand(kHeapObjectTag));
3946 __ vldr(d0, r5, HeapNumber::kValueOffset); 3949 __ vldr(d0, r5, HeapNumber::kValueOffset);
3950 __ EmitECMATruncate(r5, d0, s2, r6, r7, r9);
3947 3951
3948 __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits); 3952 switch (elements_kind) {
3949 // NaNs and Infinities have all-one exponents so they sign extend to -1. 3953 case JSObject::EXTERNAL_BYTE_ELEMENTS:
3950 __ cmp(r6, Operand(-1)); 3954 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
3951 __ mov(r5, Operand(0), LeaveCC, eq);
3952
3953 // Not infinity or NaN simply convert to int.
3954 if (IsElementTypeSigned(array_type)) {
3955 __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne);
3956 } else {
3957 __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne);
3958 }
3959 __ vmov(r5, s0, ne);
3960
3961 switch (array_type) {
3962 case kExternalByteArray:
3963 case kExternalUnsignedByteArray:
3964 __ strb(r5, MemOperand(r3, r4, LSL, 0)); 3955 __ strb(r5, MemOperand(r3, r4, LSL, 0));
3965 break; 3956 break;
3966 case kExternalShortArray: 3957 case JSObject::EXTERNAL_SHORT_ELEMENTS:
3967 case kExternalUnsignedShortArray: 3958 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
3968 __ strh(r5, MemOperand(r3, r4, LSL, 1)); 3959 __ strh(r5, MemOperand(r3, r4, LSL, 1));
3969 break; 3960 break;
3970 case kExternalIntArray: 3961 case JSObject::EXTERNAL_INT_ELEMENTS:
3971 case kExternalUnsignedIntArray: 3962 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
3972 __ str(r5, MemOperand(r3, r4, LSL, 2)); 3963 __ str(r5, MemOperand(r3, r4, LSL, 2));
3973 break; 3964 break;
3974 default: 3965 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
3966 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
3967 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
3968 case JSObject::FAST_ELEMENTS:
3969 case JSObject::FAST_DOUBLE_ELEMENTS:
3970 case JSObject::DICTIONARY_ELEMENTS:
3971 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
3975 UNREACHABLE(); 3972 UNREACHABLE();
3976 break; 3973 break;
3977 } 3974 }
3978 } 3975 }
3979 3976
3980 // Entry registers are intact, r0 holds the value which is the return 3977 // Entry registers are intact, r0 holds the value which is the return
3981 // value. 3978 // value.
3982 __ Ret(); 3979 __ Ret();
3983 } else { 3980 } else {
3984 // VFP3 is not available do manual conversions. 3981 // VFP3 is not available do manual conversions.
3985 __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); 3982 __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
3986 __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); 3983 __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
3987 3984
3988 if (array_type == kExternalFloatArray) { 3985 if (elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) {
3989 Label done, nan_or_infinity_or_zero; 3986 Label done, nan_or_infinity_or_zero;
3990 static const int kMantissaInHiWordShift = 3987 static const int kMantissaInHiWordShift =
3991 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; 3988 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
3992 3989
3993 static const int kMantissaInLoWordShift = 3990 static const int kMantissaInLoWordShift =
3994 kBitsPerInt - kMantissaInHiWordShift; 3991 kBitsPerInt - kMantissaInHiWordShift;
3995 3992
3996 // Test for all special exponent values: zeros, subnormal numbers, NaNs 3993 // Test for all special exponent values: zeros, subnormal numbers, NaNs
3997 // and infinities. All these should be converted to 0. 3994 // and infinities. All these should be converted to 0.
3998 __ mov(r7, Operand(HeapNumber::kExponentMask)); 3995 __ mov(r7, Operand(HeapNumber::kExponentMask));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4030 // value. 4027 // value.
4031 __ Ret(); 4028 __ Ret();
4032 4029
4033 __ bind(&nan_or_infinity_or_zero); 4030 __ bind(&nan_or_infinity_or_zero);
4034 __ and_(r7, r5, Operand(HeapNumber::kSignMask)); 4031 __ and_(r7, r5, Operand(HeapNumber::kSignMask));
4035 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); 4032 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
4036 __ orr(r9, r9, r7); 4033 __ orr(r9, r9, r7);
4037 __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift)); 4034 __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
4038 __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift)); 4035 __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
4039 __ b(&done); 4036 __ b(&done);
4040 } else if (array_type == kExternalDoubleArray) { 4037 } else if (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS) {
4041 __ add(r7, r3, Operand(r4, LSL, 3)); 4038 __ add(r7, r3, Operand(r4, LSL, 3));
4042 // r7: effective address of destination element. 4039 // r7: effective address of destination element.
4043 __ str(r6, MemOperand(r7, 0)); 4040 __ str(r6, MemOperand(r7, 0));
4044 __ str(r5, MemOperand(r7, Register::kSizeInBytes)); 4041 __ str(r5, MemOperand(r7, Register::kSizeInBytes));
4045 __ Ret(); 4042 __ Ret();
4046 } else { 4043 } else {
4047 bool is_signed_type = IsElementTypeSigned(array_type); 4044 bool is_signed_type = IsElementTypeSigned(elements_kind);
4048 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; 4045 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
4049 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; 4046 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
4050 4047
4051 Label done, sign; 4048 Label done, sign;
4052 4049
4053 // Test for all special exponent values: zeros, subnormal numbers, NaNs 4050 // Test for all special exponent values: zeros, subnormal numbers, NaNs
4054 // and infinities. All these should be converted to 0. 4051 // and infinities. All these should be converted to 0.
4055 __ mov(r7, Operand(HeapNumber::kExponentMask)); 4052 __ mov(r7, Operand(HeapNumber::kExponentMask));
4056 __ and_(r9, r5, Operand(r7), SetCC); 4053 __ and_(r9, r5, Operand(r7), SetCC);
4057 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); 4054 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
(...skipping 26 matching lines...) Expand all
4084 __ rsb(r9, r9, Operand(0, RelocInfo::NONE)); 4081 __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
4085 __ mov(r5, Operand(r5, LSL, r9)); 4082 __ mov(r5, Operand(r5, LSL, r9));
4086 __ rsb(r9, r9, Operand(meaningfull_bits)); 4083 __ rsb(r9, r9, Operand(meaningfull_bits));
4087 __ orr(r5, r5, Operand(r6, LSR, r9)); 4084 __ orr(r5, r5, Operand(r6, LSR, r9));
4088 4085
4089 __ bind(&sign); 4086 __ bind(&sign);
4090 __ teq(r7, Operand(0, RelocInfo::NONE)); 4087 __ teq(r7, Operand(0, RelocInfo::NONE));
4091 __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); 4088 __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
4092 4089
4093 __ bind(&done); 4090 __ bind(&done);
4094 switch (array_type) { 4091 switch (elements_kind) {
4095 case kExternalByteArray: 4092 case JSObject::EXTERNAL_BYTE_ELEMENTS:
4096 case kExternalUnsignedByteArray: 4093 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
4097 __ strb(r5, MemOperand(r3, r4, LSL, 0)); 4094 __ strb(r5, MemOperand(r3, r4, LSL, 0));
4098 break; 4095 break;
4099 case kExternalShortArray: 4096 case JSObject::EXTERNAL_SHORT_ELEMENTS:
4100 case kExternalUnsignedShortArray: 4097 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
4101 __ strh(r5, MemOperand(r3, r4, LSL, 1)); 4098 __ strh(r5, MemOperand(r3, r4, LSL, 1));
4102 break; 4099 break;
4103 case kExternalIntArray: 4100 case JSObject::EXTERNAL_INT_ELEMENTS:
4104 case kExternalUnsignedIntArray: 4101 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS:
4105 __ str(r5, MemOperand(r3, r4, LSL, 2)); 4102 __ str(r5, MemOperand(r3, r4, LSL, 2));
4106 break; 4103 break;
4107 default: 4104 case JSObject::EXTERNAL_PIXEL_ELEMENTS:
4105 case JSObject::EXTERNAL_FLOAT_ELEMENTS:
4106 case JSObject::EXTERNAL_DOUBLE_ELEMENTS:
4107 case JSObject::FAST_ELEMENTS:
4108 case JSObject::FAST_DOUBLE_ELEMENTS:
4109 case JSObject::DICTIONARY_ELEMENTS:
4110 case JSObject::NON_STRICT_ARGUMENTS_ELEMENTS:
4108 UNREACHABLE(); 4111 UNREACHABLE();
4109 break; 4112 break;
4110 } 4113 }
4111 } 4114 }
4112 } 4115 }
4113 } 4116 }
4114 4117
4115 // Slow case, key and receiver still in r0 and r1. 4118 // Slow case, key and receiver still in r0 and r1.
4116 __ bind(&slow); 4119 __ bind(&slow);
4117 __ IncrementCounter( 4120 __ IncrementCounter(
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
4198 Register value_reg = r0; 4201 Register value_reg = r0;
4199 Register key_reg = r1; 4202 Register key_reg = r1;
4200 Register receiver_reg = r2; 4203 Register receiver_reg = r2;
4201 Register scratch = r3; 4204 Register scratch = r3;
4202 Register elements_reg = r4; 4205 Register elements_reg = r4;
4203 4206
4204 // This stub is meant to be tail-jumped to, the receiver must already 4207 // This stub is meant to be tail-jumped to, the receiver must already
4205 // have been verified by the caller to not be a smi. 4208 // have been verified by the caller to not be a smi.
4206 4209
4207 // Check that the key is a smi. 4210 // Check that the key is a smi.
4208 __ JumpIfNotSmi(r0, &miss_force_generic); 4211 __ JumpIfNotSmi(key_reg, &miss_force_generic);
4209 4212
4210 // Get the elements array and make sure it is a fast element array, not 'cow'. 4213 // Get the elements array and make sure it is a fast element array, not 'cow'.
4211 __ ldr(elements_reg, 4214 __ ldr(elements_reg,
4212 FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 4215 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4213 __ CheckMap(elements_reg, 4216 __ CheckMap(elements_reg,
4214 scratch, 4217 scratch,
4215 Heap::kFixedArrayMapRootIndex, 4218 Heap::kFixedArrayMapRootIndex,
4216 &miss_force_generic, 4219 &miss_force_generic,
4217 DONT_DO_SMI_CHECK); 4220 DONT_DO_SMI_CHECK);
4218 4221
(...skipping 30 matching lines...) Expand all
4249 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4252 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4250 __ Jump(ic, RelocInfo::CODE_TARGET); 4253 __ Jump(ic, RelocInfo::CODE_TARGET);
4251 } 4254 }
4252 4255
4253 4256
4254 #undef __ 4257 #undef __
4255 4258
4256 } } // namespace v8::internal 4259 } } // namespace v8::internal
4257 4260
4258 #endif // V8_TARGET_ARCH_ARM 4261 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/regexp-macro-assembler-arm.cc ('k') | src/array.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698