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

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

Issue 11277: More work on completing Keyed IC code on ARM port.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 1 month 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
« src/ic-arm.cc ('K') | « src/stub-cache.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 283 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
284 __ cmp(scratch, Operand(JS_ARRAY_TYPE)); 284 __ cmp(scratch, Operand(JS_ARRAY_TYPE));
285 __ b(ne, miss_label); 285 __ b(ne, miss_label);
286 286
287 // Load length directly from the JS array. 287 // Load length directly from the JS array.
288 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 288 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
289 __ Ret(); 289 __ Ret();
290 } 290 }
291 291
292 292
293 // Generate code to check if an object is a string. If the object is
294 // a string, the map's instance type is left in the scratch1 register.
295 static void GenerateStringCheck(MacroAssembler* masm,
296 Register receiver,
297 Register scratch1,
298 Register scratch2,
299 Label* smi,
300 Label* non_string_object) {
301 // Check that the receiver isn't a smi.
302 __ tst(receiver, Operand(kSmiTagMask));
303 __ b(eq, smi);
304
305 // Check that the object is a string.
306 __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
307 __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
308 __ and_(scratch2, scratch1, Operand(kIsNotStringMask));
309 // The cast is to resolve the overload for the argument of 0x0.
310 __ cmp(scratch2, Operand(static_cast<int32_t>(kStringTag)));
311 __ b(ne, non_string_object);
312 }
313
314
315 void StubCompiler::GenerateLoadStringLength2(MacroAssembler* masm,
316 Register receiver,
317 Register scratch1,
318 Register scratch2,
319 Label* miss) {
320 Label load_length, check_wrapper;
321
322 // Check if the object is a string leaving the instance type in the
323 // scratch1 register.
324 GenerateStringCheck(masm, receiver, scratch1, scratch2,
325 miss, &check_wrapper);
326
327 // Load length directly from the string.
328 __ bind(&load_length);
329 __ and_(scratch1, scratch1, Operand(kStringSizeMask));
330 __ add(scratch1, scratch1, Operand(String::kHashShift));
331 __ ldr(r0, FieldMemOperand(receiver, String::kLengthOffset));
332 __ mov(r0, Operand(r0, LSR, scratch1));
333 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
334 __ Ret();
335
336 // Check if the object is a JSValue wrapper.
337 __ bind(&check_wrapper);
338 __ cmp(scratch1, Operand(JS_VALUE_TYPE));
339 __ b(ne, miss);
340
341 // Check if the wrapped value is a string and load the length
342 // directly if it is.
343 __ ldr(r0, FieldMemOperand(receiver, JSValue::kValueOffset));
344 GenerateStringCheck(masm, receiver, scratch1, scratch1, miss, miss);
345 __ b(&load_length);
346 }
347
348
349 // Generate StoreField code, value is passed in r0 register.
350 // After executing generated code, the receiver_reg and name_reg
351 // may be clobbered.
352 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
353 Builtins::Name storage_extend,
354 JSObject* object,
355 int index,
356 Map* transition,
357 Register receiver_reg,
358 Register name_reg,
359 Register scratch,
360 Label* miss_label) {
361 // r0 : value
362 Label exit;
363
364 // Check that the receiver isn't a smi.
365 __ tst(receiver_reg, Operand(kSmiTagMask));
366 __ b(eq, miss_label);
367
368 // Check that the map of the receiver hasn't changed.
369 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
370 __ cmp(scratch, Operand(Handle<Map>(object->map())));
371 __ b(ne, miss_label);
372
373 // Perform global security token check if needed.
374 if (object->IsJSGlobalProxy()) {
375 __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label);
376 }
377
378 // Stub never generated for non-global objects that require access
379 // checks.
380 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
381
382 // Perform map transition for the receiver if necessary.
383 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
384 // The properties must be extended before we can store the value.
385 // We jump to a runtime call that extends the propeties array.
386 __ mov(r2, Operand(Handle<Map>(transition)));
387 // Please note, if we implement keyed store for arm we need
388 // to call the Builtins::KeyedStoreIC_ExtendStorage.
389 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
390 __ Jump(ic, RelocInfo::CODE_TARGET);
391 return;
392 }
393
394 if (transition != NULL) {
395 // Update the map of the object; no write barrier updating is
396 // needed because the map is never in new space.
397 __ mov(ip, Operand(Handle<Map>(transition)));
398 __ str(ip, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
399 }
400
401 // Adjust for the number of properties stored in the object. Even in the
402 // face of a transition we can use the old map here because the size of the
403 // object and the number of in-object properties is not going to change.
404 index -= object->map()->inobject_properties();
405
406 if (index < 0) {
407 // Set the property straight into the object.
408 int offset = object->map()->instance_size() + (index * kPointerSize);
409 __ str(r0, FieldMemOperand(receiver_reg, offset));
410
411 // Skip updating write barrier if storing a smi.
412 __ tst(r0, Operand(kSmiTagMask));
413 __ b(eq, &exit);
414
415 // Update the write barrier for the array address.
416 // Pass the value being stored in the now unused name_reg.
417 __ mov(name_reg, Operand(offset));
418 __ RecordWrite(receiver_reg, name_reg, scratch);
419 } else {
420 // Write to the properties array.
421 int offset = index * kPointerSize + Array::kHeaderSize;
422 // Get the properties array
423 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
424 __ str(r0, FieldMemOperand(scratch, offset));
425
426 // Skip updating write barrier if storing a smi.
427 __ tst(r0, Operand(kSmiTagMask));
428 __ b(eq, &exit);
429
430 // Update the write barrier for the array address.
431 // Ok to clobber receiver_reg and name_reg, since we return.
432 __ mov(name_reg, Operand(offset));
433 __ RecordWrite(scratch, name_reg, receiver_reg);
434 }
435
436 // Return the value (register r0).
437 __ bind(&exit);
438 __ Ret();
439 }
440
441
293 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 442 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
294 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 443 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
295 Code* code = NULL; 444 Code* code = NULL;
296 if (kind == Code::LOAD_IC) { 445 if (kind == Code::LOAD_IC) {
297 code = Builtins::builtin(Builtins::LoadIC_Miss); 446 code = Builtins::builtin(Builtins::LoadIC_Miss);
298 } else { 447 } else {
299 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss); 448 code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
300 } 449 }
301 450
302 Handle<Code> ic(code); 451 Handle<Code> ic(code);
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
545 Map* transition, 694 Map* transition,
546 String* name) { 695 String* name) {
547 // ----------- S t a t e ------------- 696 // ----------- S t a t e -------------
548 // -- r0 : value 697 // -- r0 : value
549 // -- r2 : name 698 // -- r2 : name
550 // -- lr : return address 699 // -- lr : return address
551 // -- [sp] : receiver 700 // -- [sp] : receiver
552 // ----------------------------------- 701 // -----------------------------------
553 702
554 HandleScope scope; 703 HandleScope scope;
555 Label miss, exit; 704 Label miss;
556 705
557 // Get the receiver from the stack. 706 // Get the receiver from the stack.
558 __ ldr(r3, MemOperand(sp, 0 * kPointerSize)); 707 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
559 708
560 // Check that the receiver isn't a smi. 709 // name register might be clobbered.
561 __ tst(r3, Operand(kSmiTagMask)); 710 GenerateStoreField(masm(),
562 __ b(eq, &miss); 711 Builtins::StoreIC_ExtendStorage,
563 712 object,
564 // Check that the map of the receiver hasn't changed. 713 index,
565 __ ldr(r1, FieldMemOperand(r3, HeapObject::kMapOffset)); 714 transition,
566 __ cmp(r1, Operand(Handle<Map>(object->map()))); 715 r3, r2, r1,
567 __ b(ne, &miss); 716 &miss);
568
569 // Perform global security token check if needed.
570 if (object->IsJSGlobalProxy()) {
571 __ CheckAccessGlobalProxy(r3, r1, &miss);
572 }
573
574 // Stub never generated for non-global objects that require access
575 // checks.
576 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
577
578 // Perform map transition for the receiver if necessary.
579 if ((transition != NULL) && (object->map()->unused_property_fields() == 0)) {
580 // The properties must be extended before we can store the value.
581 // We jump to a runtime call that extends the propeties array.
582 __ mov(r2, Operand(Handle<Map>(transition)));
583 // Please note, if we implement keyed store for arm we need
584 // to call the Builtins::KeyedStoreIC_ExtendStorage.
585 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_ExtendStorage));
586 __ Jump(ic, RelocInfo::CODE_TARGET);
587 } else {
588 // Adjust for the number of properties stored in the object. Even in the
589 // face of a transition we can use the old map here because the size of the
590 // object and the number of in-object properties is not going to change.
591 index -= object->map()->inobject_properties();
592
593 if (index >= 0) {
594 // Get the properties array
595 __ ldr(r1, FieldMemOperand(r3, JSObject::kPropertiesOffset));
596 }
597
598 if (transition != NULL) {
599 // Update the map of the object; no write barrier updating is
600 // needed because the map is never in new space.
601 __ mov(ip, Operand(Handle<Map>(transition)));
602 __ str(ip, FieldMemOperand(r3, HeapObject::kMapOffset));
603 }
604
605 if (index < 0) {
606 // Set the property straight into the object.
607 int offset = object->map()->instance_size() + (index * kPointerSize);
608 __ str(r0, FieldMemOperand(r3, offset));
609
610 // Skip updating write barrier if storing a smi.
611 __ tst(r0, Operand(kSmiTagMask));
612 __ b(eq, &exit);
613
614 // Update the write barrier for the array address.
615 __ mov(r1, Operand(offset));
616 __ RecordWrite(r3, r1, r2);
617 } else {
618 // Write to the properties array.
619 int offset = index * kPointerSize + Array::kHeaderSize;
620 __ str(r0, FieldMemOperand(r1, offset));
621
622 // Skip updating write barrier if storing a smi.
623 __ tst(r0, Operand(kSmiTagMask));
624 __ b(eq, &exit);
625
626 // Update the write barrier for the array address.
627 __ mov(r3, Operand(offset));
628 __ RecordWrite(r1, r3, r2); // OK to clobber r2, since we return
629 }
630
631 // Return the value (register r0).
632 __ bind(&exit);
633 __ Ret();
634 }
635 // Handle store cache miss.
636 __ bind(&miss); 717 __ bind(&miss);
637 __ mov(r2, Operand(Handle<String>(name))); // restore name 718 __ mov(r2, Operand(Handle<String>(name))); // restore name
638 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 719 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
639 __ Jump(ic, RelocInfo::CODE_TARGET); 720 __ Jump(ic, RelocInfo::CODE_TARGET);
640 721
641 // Return the generated code. 722 // Return the generated code.
642 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION); 723 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
643 } 724 }
644 725
645 726
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 __ b(ne, &miss); 1052 __ b(ne, &miss);
972 1053
973 GenerateLoadArrayLength(masm(), r0, r3, &miss); 1054 GenerateLoadArrayLength(masm(), r0, r3, &miss);
974 __ bind(&miss); 1055 __ bind(&miss);
975 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1056 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
976 1057
977 return GetCode(CALLBACKS); 1058 return GetCode(CALLBACKS);
978 } 1059 }
979 1060
980 1061
981 // TODO(1224671): implement the fast case.
982 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) { 1062 Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
983 // ----------- S t a t e ------------- 1063 // ----------- S t a t e -------------
984 // -- lr : return address 1064 // -- lr : return address
985 // -- sp[0] : key 1065 // -- sp[0] : key
986 // -- sp[4] : receiver 1066 // -- sp[4] : receiver
987 // ----------------------------------- 1067 // -----------------------------------
988 HandleScope scope; 1068 HandleScope scope;
1069
1070 Label miss;
1071 __ IncrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1072
1073 __ ldr(r2, MemOperand(sp));
1074 __ ldr(r0, MemOperand(sp, kPointerSize)); // receiver
1075
1076 __ cmp(r2, Operand(Handle<String>(name)));
1077 __ b(ne, &miss);
1078
1079 GenerateLoadStringLength2(masm(), r0, r1, r3, &miss);
1080 __ bind(&miss);
1081 __ DecrementCounter(&Counters::keyed_load_string_length, 1, r1, r3);
1082
989 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1083 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
990 1084
991 return GetCode(CALLBACKS); 1085 return GetCode(CALLBACKS);
992 } 1086 }
993 1087
994 1088
995 // TODO(1224671): implement the fast case. 1089 // TODO(1224671): implement the fast case.
996 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { 1090 Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
997 // ----------- S t a t e ------------- 1091 // ----------- S t a t e -------------
998 // -- lr : return address 1092 // -- lr : return address
999 // -- sp[0] : key 1093 // -- sp[0] : key
1000 // -- sp[4] : receiver 1094 // -- sp[4] : receiver
1001 // ----------------------------------- 1095 // -----------------------------------
1002 HandleScope scope; 1096 HandleScope scope;
1003 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 1097 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
1004 1098
1005 return GetCode(CALLBACKS); 1099 return GetCode(CALLBACKS);
1006 } 1100 }
1007 1101
1008 1102
1009 // TODO(1224671): implement the fast case.
1010 Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 1103 Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
1011 int index, 1104 int index,
1012 Map* transition, 1105 Map* transition,
1013 String* name) { 1106 String* name) {
1014 // ----------- S t a t e ------------- 1107 // ----------- S t a t e -------------
1015 // -- r0 : value 1108 // -- r0 : value
1016 // -- r2 : name 1109 // -- r2 : name
1017 // -- lr : return address 1110 // -- lr : return address
1018 // -- [sp] : receiver 1111 // -- [sp] : receiver
1019 // ----------------------------------- 1112 // -----------------------------------
1020 HandleScope scope; 1113 HandleScope scope;
1114 Label miss;
1115
1116 __ IncrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1117
1118 // Check that the name has not changed.
1119 __ cmp(r2, Operand(Handle<String>(name)));
1120 __ b(ne, &miss);
1121
1122 // Load receiver from the stack.
1123 __ ldr(r3, MemOperand(sp));
1124 // r1 is used as scratch register, r3 and r2 might be clobbered.
1125 GenerateStoreField(masm(),
1126 Builtins::StoreIC_ExtendStorage,
1127 object,
1128 index,
1129 transition,
1130 r3, r2, r1,
1131 &miss);
1132 __ bind(&miss);
1133
1134 __ DecrementCounter(&Counters::keyed_store_field, 1, r1, r3);
1135 __ mov(r2, Operand(Handle<String>(name))); // restore name register.
1021 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 1136 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
1022 __ Jump(ic, RelocInfo::CODE_TARGET); 1137 __ Jump(ic, RelocInfo::CODE_TARGET);
1023 1138
1024 // Return the generated code. 1139 // Return the generated code.
1025 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION); 1140 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
1026 } 1141 }
1027 1142
1028 1143
1029 #undef __ 1144 #undef __
1030 1145
1031 } } // namespace v8::internal 1146 } } // namespace v8::internal
OLDNEW
« src/ic-arm.cc ('K') | « src/stub-cache.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698