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

Side by Side Diff: src/ic/arm/handler-compiler-arm.cc

Issue 609463003: Hydrogenize (and share) part of StoreTransition handler as a StoreTransitionStub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebasing Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/interface-descriptors-ia32.cc ('k') | src/ic/arm64/handler-compiler-arm64.cc » ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_ARM 7 #if V8_TARGET_ARCH_ARM
8 8
9 #include "src/ic/call-optimization.h" 9 #include "src/ic/call-optimization.h"
10 #include "src/ic/handler-compiler.h" 10 #include "src/ic/handler-compiler.h"
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 319
320 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label, 320 void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
321 Handle<Name> name) { 321 Handle<Name> name) {
322 if (!label->is_unused()) { 322 if (!label->is_unused()) {
323 __ bind(label); 323 __ bind(label);
324 __ mov(this->name(), Operand(name)); 324 __ mov(this->name(), Operand(name));
325 } 325 }
326 } 326 }
327 327
328 328
329 // Generate StoreTransition code, value is passed in r0 register. 329 void NamedStoreHandlerCompiler::GenerateRestoreNameAndMap(
330 // When leaving generated code after success, the receiver_reg and name_reg 330 Handle<Name> name, Handle<Map> transition) {
331 // may be clobbered. Upon branch to miss_label, the receiver and name 331 __ mov(this->name(), Operand(name));
332 // registers have their original values. 332 __ mov(StoreTransitionDescriptor::MapRegister(), Operand(transition));
333 void NamedStoreHandlerCompiler::GenerateStoreTransition(
334 Handle<Map> transition, Handle<Name> name, Register receiver_reg,
335 Register storage_reg, Register value_reg, Register scratch1,
336 Register scratch2, Register scratch3, Label* miss_label, Label* slow) {
337 // r0 : value
338 Label exit;
339
340 int descriptor = transition->LastAdded();
341 DescriptorArray* descriptors = transition->instance_descriptors();
342 PropertyDetails details = descriptors->GetDetails(descriptor);
343 Representation representation = details.representation();
344 DCHECK(!representation.IsNone());
345
346 if (details.type() == CONSTANT) {
347 Handle<Object> constant(descriptors->GetValue(descriptor), isolate());
348 __ Move(scratch1, constant);
349 __ cmp(value_reg, scratch1);
350 __ b(ne, miss_label);
351 } else if (representation.IsSmi()) {
352 __ JumpIfNotSmi(value_reg, miss_label);
353 } else if (representation.IsHeapObject()) {
354 __ JumpIfSmi(value_reg, miss_label);
355 HeapType* field_type = descriptors->GetFieldType(descriptor);
356 HeapType::Iterator<Map> it = field_type->Classes();
357 if (!it.Done()) {
358 __ ldr(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset));
359 Label do_store;
360 while (true) {
361 __ CompareMap(scratch1, it.Current(), &do_store);
362 it.Advance();
363 if (it.Done()) {
364 __ b(ne, miss_label);
365 break;
366 }
367 __ b(eq, &do_store);
368 }
369 __ bind(&do_store);
370 }
371 } else if (representation.IsDouble()) {
372 Label do_store, heap_number;
373 __ LoadRoot(scratch3, Heap::kMutableHeapNumberMapRootIndex);
374 __ AllocateHeapNumber(storage_reg, scratch1, scratch2, scratch3, slow,
375 TAG_RESULT, MUTABLE);
376
377 __ JumpIfNotSmi(value_reg, &heap_number);
378 __ SmiUntag(scratch1, value_reg);
379 __ vmov(s0, scratch1);
380 __ vcvt_f64_s32(d0, s0);
381 __ jmp(&do_store);
382
383 __ bind(&heap_number);
384 __ CheckMap(value_reg, scratch1, Heap::kHeapNumberMapRootIndex, miss_label,
385 DONT_DO_SMI_CHECK);
386 __ vldr(d0, FieldMemOperand(value_reg, HeapNumber::kValueOffset));
387
388 __ bind(&do_store);
389 __ vstr(d0, FieldMemOperand(storage_reg, HeapNumber::kValueOffset));
390 }
391
392 // Stub never generated for objects that require access checks.
393 DCHECK(!transition->is_access_check_needed());
394
395 // Perform map transition for the receiver if necessary.
396 if (details.type() == FIELD &&
397 Map::cast(transition->GetBackPointer())->unused_property_fields() == 0) {
398 // The properties must be extended before we can store the value.
399 __ mov(ExtendStorageDescriptor::NameRegister(), Operand(name));
400 __ mov(ExtendStorageDescriptor::MapRegister(), Operand(transition));
401
402 ExtendStorageStub stub(isolate(),
403 FieldIndex::ForDescriptor(*transition, descriptor),
404 representation);
405 GenerateTailCall(masm(), stub.GetCode());
406 return;
407 }
408
409 // Update the map of the object.
410 __ mov(scratch1, Operand(transition));
411 __ str(scratch1, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
412
413 // Update the write barrier for the map field.
414 __ RecordWriteField(receiver_reg, HeapObject::kMapOffset, scratch1, scratch2,
415 kLRHasNotBeenSaved, kDontSaveFPRegs, OMIT_REMEMBERED_SET,
416 OMIT_SMI_CHECK);
417
418 if (details.type() == CONSTANT) {
419 DCHECK(value_reg.is(r0));
420 __ Ret();
421 return;
422 }
423
424 int index = transition->instance_descriptors()->GetFieldIndex(
425 transition->LastAdded());
426
427 // Adjust for the number of properties stored in the object. Even in the
428 // face of a transition we can use the old map here because the size of the
429 // object and the number of in-object properties is not going to change.
430 index -= transition->inobject_properties();
431
432 // TODO(verwaest): Share this code as a code stub.
433 SmiCheck smi_check =
434 representation.IsTagged() ? INLINE_SMI_CHECK : OMIT_SMI_CHECK;
435 if (index < 0) {
436 // Set the property straight into the object.
437 int offset = transition->instance_size() + (index * kPointerSize);
438 if (representation.IsDouble()) {
439 __ str(storage_reg, FieldMemOperand(receiver_reg, offset));
440 } else {
441 __ str(value_reg, FieldMemOperand(receiver_reg, offset));
442 }
443
444 if (!representation.IsSmi()) {
445 // Update the write barrier for the array address.
446 if (!representation.IsDouble()) {
447 __ mov(storage_reg, value_reg);
448 }
449 __ RecordWriteField(receiver_reg, offset, storage_reg, scratch1,
450 kLRHasNotBeenSaved, kDontSaveFPRegs,
451 EMIT_REMEMBERED_SET, smi_check);
452 }
453 } else {
454 // Write to the properties array.
455 int offset = index * kPointerSize + FixedArray::kHeaderSize;
456 // Get the properties array
457 __ ldr(scratch1,
458 FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset));
459 if (representation.IsDouble()) {
460 __ str(storage_reg, FieldMemOperand(scratch1, offset));
461 } else {
462 __ str(value_reg, FieldMemOperand(scratch1, offset));
463 }
464
465 if (!representation.IsSmi()) {
466 // Update the write barrier for the array address.
467 if (!representation.IsDouble()) {
468 __ mov(storage_reg, value_reg);
469 }
470 __ RecordWriteField(scratch1, offset, storage_reg, receiver_reg,
471 kLRHasNotBeenSaved, kDontSaveFPRegs,
472 EMIT_REMEMBERED_SET, smi_check);
473 }
474 }
475
476 // Return the value (register r0).
477 DCHECK(value_reg.is(r0));
478 __ bind(&exit);
479 __ Ret();
480 } 333 }
481 334
482 335
483 void NamedStoreHandlerCompiler::GenerateStoreField(LookupIterator* lookup, 336 void NamedStoreHandlerCompiler::GenerateConstantCheck(Object* constant,
484 Register value_reg, 337 Register value_reg,
485 Label* miss_label) { 338 Label* miss_label) {
486 DCHECK(lookup->representation().IsHeapObject()); 339 __ Move(scratch1(), handle(constant, isolate()));
487 __ JumpIfSmi(value_reg, miss_label); 340 __ cmp(value_reg, scratch1());
488 HeapType::Iterator<Map> it = lookup->GetFieldType()->Classes(); 341 __ b(ne, miss_label);
489 __ ldr(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset));
490 Label do_store;
491 while (true) {
492 __ CompareMap(scratch1(), it.Current(), &do_store);
493 it.Advance();
494 if (it.Done()) {
495 __ b(ne, miss_label);
496 break;
497 }
498 __ b(eq, &do_store);
499 }
500 __ bind(&do_store);
501
502 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(),
503 lookup->representation());
504 GenerateTailCall(masm(), stub.GetCode());
505 } 342 }
506 343
507 344
345 void NamedStoreHandlerCompiler::GenerateFieldTypeChecks(HeapType* field_type,
346 Register value_reg,
347 Label* miss_label) {
348 __ JumpIfSmi(value_reg, miss_label);
349 HeapType::Iterator<Map> it = field_type->Classes();
350 if (!it.Done()) {
351 __ ldr(scratch1(), FieldMemOperand(value_reg, HeapObject::kMapOffset));
352 Label do_store;
353 while (true) {
354 __ CompareMap(scratch1(), it.Current(), &do_store);
355 it.Advance();
356 if (it.Done()) {
357 __ b(ne, miss_label);
358 break;
359 }
360 __ b(eq, &do_store);
361 }
362 __ bind(&do_store);
363 }
364 }
365
366
508 Register PropertyHandlerCompiler::CheckPrototypes( 367 Register PropertyHandlerCompiler::CheckPrototypes(
509 Register object_reg, Register holder_reg, Register scratch1, 368 Register object_reg, Register holder_reg, Register scratch1,
510 Register scratch2, Handle<Name> name, Label* miss, 369 Register scratch2, Handle<Name> name, Label* miss,
511 PrototypeCheckType check) { 370 PrototypeCheckType check) {
512 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate())); 371 Handle<Map> receiver_map(IC::TypeToMap(*type(), isolate()));
513 372
514 // Make sure there's no overlap between holder and object registers. 373 // Make sure there's no overlap between holder and object registers.
515 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 374 DCHECK(!scratch1.is(object_reg) && !scratch1.is(holder_reg));
516 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) && 375 DCHECK(!scratch2.is(object_reg) && !scratch2.is(holder_reg) &&
517 !scratch2.is(scratch1)); 376 !scratch2.is(scratch1));
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 // Return the generated code. 689 // Return the generated code.
831 return GetCode(kind(), Code::NORMAL, name); 690 return GetCode(kind(), Code::NORMAL, name);
832 } 691 }
833 692
834 693
835 #undef __ 694 #undef __
836 } 695 }
837 } // namespace v8::internal 696 } // namespace v8::internal
838 697
839 #endif // V8_TARGET_ARCH_ARM 698 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/ia32/interface-descriptors-ia32.cc ('k') | src/ic/arm64/handler-compiler-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698