compiler/optimizing/code_generator_x86.cc [5380:5457]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        codegen_->AddSlowPath(slow_path);
        if (instruction->GetValueCanBeNull()) {
          __ testl(register_value, register_value);
          __ j(kNotEqual, &not_null);
          __ movl(address, Immediate(0));
          codegen_->MaybeRecordImplicitNullCheck(instruction);
          __ jmp(&done);
          __ Bind(&not_null);
        }

        if (kEmitCompilerReadBarrier) {
          // When read barriers are enabled, the type checking
          // instrumentation requires two read barriers:
          //
          //   __ movl(temp2, temp);
          //   // /* HeapReference<Class> */ temp = temp->component_type_
          //   __ movl(temp, Address(temp, component_offset));
          //   codegen_->GenerateReadBarrierSlow(
          //       instruction, temp_loc, temp_loc, temp2_loc, component_offset);
          //
          //   // /* HeapReference<Class> */ temp2 = register_value->klass_
          //   __ movl(temp2, Address(register_value, class_offset));
          //   codegen_->GenerateReadBarrierSlow(
          //       instruction, temp2_loc, temp2_loc, value, class_offset, temp_loc);
          //
          //   __ cmpl(temp, temp2);
          //
          // However, the second read barrier may trash `temp`, as it
          // is a temporary register, and as such would not be saved
          // along with live registers before calling the runtime (nor
          // restored afterwards).  So in this case, we bail out and
          // delegate the work to the array set slow path.
          //
          // TODO: Extend the register allocator to support a new
          // "(locally) live temp" location so as to avoid always
          // going into the slow path when read barriers are enabled.
          __ jmp(slow_path->GetEntryLabel());
        } else {
          // /* HeapReference<Class> */ temp = array->klass_
          __ movl(temp, Address(array, class_offset));
          codegen_->MaybeRecordImplicitNullCheck(instruction);
          __ MaybeUnpoisonHeapReference(temp);

          // /* HeapReference<Class> */ temp = temp->component_type_
          __ movl(temp, Address(temp, component_offset));
          // If heap poisoning is enabled, no need to unpoison `temp`
          // nor the object reference in `register_value->klass`, as
          // we are comparing two poisoned references.
          __ cmpl(temp, Address(register_value, class_offset));

          if (instruction->StaticTypeOfArrayIsObjectArray()) {
            __ j(kEqual, &do_put);
            // If heap poisoning is enabled, the `temp` reference has
            // not been unpoisoned yet; unpoison it now.
            __ MaybeUnpoisonHeapReference(temp);

            // /* HeapReference<Class> */ temp = temp->super_class_
            __ movl(temp, Address(temp, super_offset));
            // If heap poisoning is enabled, no need to unpoison
            // `temp`, as we are comparing against null below.
            __ testl(temp, temp);
            __ j(kNotEqual, slow_path->GetEntryLabel());
            __ Bind(&do_put);
          } else {
            __ j(kNotEqual, slow_path->GetEntryLabel());
          }
        }
      }

      if (kPoisonHeapReferences) {
        __ movl(temp, register_value);
        __ PoisonHeapReference(temp);
        __ movl(address, temp);
      } else {
        __ movl(address, register_value);
      }
      if (!may_need_runtime_call_for_type_check) {
        codegen_->MaybeRecordImplicitNullCheck(instruction);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



compiler/optimizing/code_generator_x86_64.cc [4805:4882]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        codegen_->AddSlowPath(slow_path);
        if (instruction->GetValueCanBeNull()) {
          __ testl(register_value, register_value);
          __ j(kNotEqual, &not_null);
          __ movl(address, Immediate(0));
          codegen_->MaybeRecordImplicitNullCheck(instruction);
          __ jmp(&done);
          __ Bind(&not_null);
        }

        if (kEmitCompilerReadBarrier) {
          // When read barriers are enabled, the type checking
          // instrumentation requires two read barriers:
          //
          //   __ movl(temp2, temp);
          //   // /* HeapReference<Class> */ temp = temp->component_type_
          //   __ movl(temp, Address(temp, component_offset));
          //   codegen_->GenerateReadBarrierSlow(
          //       instruction, temp_loc, temp_loc, temp2_loc, component_offset);
          //
          //   // /* HeapReference<Class> */ temp2 = register_value->klass_
          //   __ movl(temp2, Address(register_value, class_offset));
          //   codegen_->GenerateReadBarrierSlow(
          //       instruction, temp2_loc, temp2_loc, value, class_offset, temp_loc);
          //
          //   __ cmpl(temp, temp2);
          //
          // However, the second read barrier may trash `temp`, as it
          // is a temporary register, and as such would not be saved
          // along with live registers before calling the runtime (nor
          // restored afterwards).  So in this case, we bail out and
          // delegate the work to the array set slow path.
          //
          // TODO: Extend the register allocator to support a new
          // "(locally) live temp" location so as to avoid always
          // going into the slow path when read barriers are enabled.
          __ jmp(slow_path->GetEntryLabel());
        } else {
          // /* HeapReference<Class> */ temp = array->klass_
          __ movl(temp, Address(array, class_offset));
          codegen_->MaybeRecordImplicitNullCheck(instruction);
          __ MaybeUnpoisonHeapReference(temp);

          // /* HeapReference<Class> */ temp = temp->component_type_
          __ movl(temp, Address(temp, component_offset));
          // If heap poisoning is enabled, no need to unpoison `temp`
          // nor the object reference in `register_value->klass`, as
          // we are comparing two poisoned references.
          __ cmpl(temp, Address(register_value, class_offset));

          if (instruction->StaticTypeOfArrayIsObjectArray()) {
            __ j(kEqual, &do_put);
            // If heap poisoning is enabled, the `temp` reference has
            // not been unpoisoned yet; unpoison it now.
            __ MaybeUnpoisonHeapReference(temp);

            // /* HeapReference<Class> */ temp = temp->super_class_
            __ movl(temp, Address(temp, super_offset));
            // If heap poisoning is enabled, no need to unpoison
            // `temp`, as we are comparing against null below.
            __ testl(temp, temp);
            __ j(kNotEqual, slow_path->GetEntryLabel());
            __ Bind(&do_put);
          } else {
            __ j(kNotEqual, slow_path->GetEntryLabel());
          }
        }
      }

      if (kPoisonHeapReferences) {
        __ movl(temp, register_value);
        __ PoisonHeapReference(temp);
        __ movl(address, temp);
      } else {
        __ movl(address, register_value);
      }
      if (!may_need_runtime_call_for_type_check) {
        codegen_->MaybeRecordImplicitNullCheck(instruction);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



