Revision f230a1cf deps/v8/src/arm/full-codegen-arm.cc

View differences:

deps/v8/src/arm/full-codegen-arm.cc
148 148
  // receiver object). r5 is zero for method calls and non-zero for
149 149
  // function calls.
150 150
  if (!info->is_classic_mode() || info->is_native()) {
151
    Label ok;
152 151
    __ cmp(r5, Operand::Zero());
153
    __ b(eq, &ok);
154 152
    int receiver_offset = info->scope()->num_parameters() * kPointerSize;
155 153
    __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
156
    __ str(r2, MemOperand(sp, receiver_offset));
157
    __ bind(&ok);
154
    __ str(r2, MemOperand(sp, receiver_offset), ne);
158 155
  }
159 156

  
160 157
  // Open a frame scope to indicate that there is a frame on the stack.  The
......
163 160
  FrameScope frame_scope(masm_, StackFrame::MANUAL);
164 161

  
165 162
  info->set_prologue_offset(masm_->pc_offset());
166
  {
167
    PredictableCodeSizeScope predictible_code_size_scope(
168
        masm_, kNoCodeAgeSequenceLength * Assembler::kInstrSize);
169
    // The following three instructions must remain together and unmodified
170
    // for code aging to work properly.
171
    __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit());
172
    __ nop(ip.code());
173
    // Adjust FP to point to saved FP.
174
    __ add(fp, sp, Operand(2 * kPointerSize));
175
  }
163
  __ Prologue(BUILD_FUNCTION_FRAME);
176 164
  info->AddNoFrameRange(0, masm_->pc_offset());
177 165

  
178 166
  { Comment cmnt(masm_, "[ Allocate locals");
......
1167 1155
      Handle<Object>(Smi::FromInt(TypeFeedbackCells::kForInFastCaseMarker),
1168 1156
                     isolate()));
1169 1157
  RecordTypeFeedbackCell(stmt->ForInFeedbackId(), cell);
1170
  __ LoadHeapObject(r1, cell);
1158
  __ Move(r1, cell);
1171 1159
  __ mov(r2, Operand(Smi::FromInt(TypeFeedbackCells::kForInSlowCaseMarker)));
1172 1160
  __ str(r2, FieldMemOperand(r1, Cell::kValueOffset));
1173 1161

  
......
1651 1639
  __ mov(r0, Operand(Smi::FromInt(flags)));
1652 1640
  int properties_count = constant_properties->length() / 2;
1653 1641
  if ((FLAG_track_double_fields && expr->may_store_doubles()) ||
1654
      expr->depth() > 1) {
1655
    __ Push(r3, r2, r1, r0);
1656
    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1657
  } else if (Serializer::enabled() || flags != ObjectLiteral::kFastElements ||
1642
      expr->depth() > 1 || Serializer::enabled() ||
1643
      flags != ObjectLiteral::kFastElements ||
1658 1644
      properties_count > FastCloneShallowObjectStub::kMaximumClonedProperties) {
1659 1645
    __ Push(r3, r2, r1, r0);
1660
    __ CallRuntime(Runtime::kCreateObjectLiteralShallow, 4);
1646
    __ CallRuntime(Runtime::kCreateObjectLiteral, 4);
1661 1647
  } else {
1662 1648
    FastCloneShallowObjectStub stub(properties_count);
1663 1649
    __ CallStub(&stub);
......
3592 3578
void FullCodeGenerator::EmitNumberToString(CallRuntime* expr) {
3593 3579
  ZoneList<Expression*>* args = expr->arguments();
3594 3580
  ASSERT_EQ(args->length(), 1);
3595
  // Load the argument on the stack and call the stub.
3596
  VisitForStackValue(args->at(0));
3581
  // Load the argument into r0 and call the stub.
3582
  VisitForAccumulatorValue(args->at(0));
3597 3583

  
3598 3584
  NumberToStringStub stub;
3599 3585
  __ CallStub(&stub);
......
3964 3950

  
3965 3951

  
3966 3952
void FullCodeGenerator::EmitFastAsciiArrayJoin(CallRuntime* expr) {
3967
  Label bailout, done, one_char_separator, long_separator,
3968
      non_trivial_array, not_size_one_array, loop,
3969
      empty_separator_loop, one_char_separator_loop,
3953
  Label bailout, done, one_char_separator, long_separator, non_trivial_array,
3954
      not_size_one_array, loop, empty_separator_loop, one_char_separator_loop,
3970 3955
      one_char_separator_loop_entry, long_separator_loop;
3971 3956
  ZoneList<Expression*>* args = expr->arguments();
3972 3957
  ASSERT(args->length() == 2);
......
3984 3969
  Register string = r4;
3985 3970
  Register element = r5;
3986 3971
  Register elements_end = r6;
3987
  Register scratch1 = r7;
3988
  Register scratch2 = r9;
3972
  Register scratch = r9;
3989 3973

  
3990 3974
  // Separator operand is on the stack.
3991 3975
  __ pop(separator);
3992 3976

  
3993 3977
  // Check that the array is a JSArray.
3994 3978
  __ JumpIfSmi(array, &bailout);
3995
  __ CompareObjectType(array, scratch1, scratch2, JS_ARRAY_TYPE);
3979
  __ CompareObjectType(array, scratch, array_length, JS_ARRAY_TYPE);
3996 3980
  __ b(ne, &bailout);
3997 3981

  
3998 3982
  // Check that the array has fast elements.
3999
  __ CheckFastElements(scratch1, scratch2, &bailout);
3983
  __ CheckFastElements(scratch, array_length, &bailout);
4000 3984

  
4001 3985
  // If the array has length zero, return the empty string.
4002 3986
  __ ldr(array_length, FieldMemOperand(array, JSArray::kLengthOffset));
......
4033 4017
  __ bind(&loop);
4034 4018
  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
4035 4019
  __ JumpIfSmi(string, &bailout);
4036
  __ ldr(scratch1, FieldMemOperand(string, HeapObject::kMapOffset));
4037
  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
4038
  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
4039
  __ ldr(scratch1, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
4040
  __ add(string_length, string_length, Operand(scratch1), SetCC);
4020
  __ ldr(scratch, FieldMemOperand(string, HeapObject::kMapOffset));
4021
  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
4022
  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout);
4023
  __ ldr(scratch, FieldMemOperand(string, SeqOneByteString::kLengthOffset));
4024
  __ add(string_length, string_length, Operand(scratch), SetCC);
4041 4025
  __ b(vs, &bailout);
4042 4026
  __ cmp(element, elements_end);
4043 4027
  __ b(lt, &loop);
......
4058 4042

  
4059 4043
  // Check that the separator is a flat ASCII string.
4060 4044
  __ JumpIfSmi(separator, &bailout);
4061
  __ ldr(scratch1, FieldMemOperand(separator, HeapObject::kMapOffset));
4062
  __ ldrb(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset));
4063
  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch1, scratch2, &bailout);
4045
  __ ldr(scratch, FieldMemOperand(separator, HeapObject::kMapOffset));
4046
  __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
4047
  __ JumpIfInstanceTypeIsNotSequentialAscii(scratch, scratch, &bailout);
4064 4048

  
4065 4049
  // Add (separator length times array_length) - separator length to the
4066 4050
  // string_length to get the length of the result string. array_length is not
4067 4051
  // smi but the other values are, so the result is a smi
4068
  __ ldr(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
4069
  __ sub(string_length, string_length, Operand(scratch1));
4070
  __ smull(scratch2, ip, array_length, scratch1);
4052
  __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
4053
  __ sub(string_length, string_length, Operand(scratch));
4054
  __ smull(scratch, ip, array_length, scratch);
4071 4055
  // Check for smi overflow. No overflow if higher 33 bits of 64-bit result are
4072 4056
  // zero.
4073 4057
  __ cmp(ip, Operand::Zero());
4074 4058
  __ b(ne, &bailout);
4075
  __ tst(scratch2, Operand(0x80000000));
4059
  __ tst(scratch, Operand(0x80000000));
4076 4060
  __ b(ne, &bailout);
4077
  __ add(string_length, string_length, Operand(scratch2), SetCC);
4061
  __ add(string_length, string_length, Operand(scratch), SetCC);
4078 4062
  __ b(vs, &bailout);
4079 4063
  __ SmiUntag(string_length);
4080 4064

  
......
4091 4075
  //   array_length: Length of the array.
4092 4076
  __ AllocateAsciiString(result,
4093 4077
                         string_length,
4094
                         scratch1,
4095
                         scratch2,
4096
                         elements_end,
4078
                         scratch,
4079
                         string,  // used as scratch
4080
                         elements_end,  // used as scratch
4097 4081
                         &bailout);
4098 4082
  // Prepare for looping. Set up elements_end to end of the array. Set
4099 4083
  // result_pos to the position of the result where to write the first
......
4106 4090
         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4107 4091

  
4108 4092
  // Check the length of the separator.
4109
  __ ldr(scratch1, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
4110
  __ cmp(scratch1, Operand(Smi::FromInt(1)));
4093
  __ ldr(scratch, FieldMemOperand(separator, SeqOneByteString::kLengthOffset));
4094
  __ cmp(scratch, Operand(Smi::FromInt(1)));
4111 4095
  __ b(eq, &one_char_separator);
4112 4096
  __ b(gt, &long_separator);
4113 4097

  
......
4125 4109
  __ add(string,
4126 4110
         string,
4127 4111
         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4128
  __ CopyBytes(string, result_pos, string_length, scratch1);
4112
  __ CopyBytes(string, result_pos, string_length, scratch);
4129 4113
  __ cmp(element, elements_end);
4130 4114
  __ b(lt, &empty_separator_loop);  // End while (element < elements_end).
4131 4115
  ASSERT(result.is(r0));
......
4157 4141
  __ add(string,
4158 4142
         string,
4159 4143
         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4160
  __ CopyBytes(string, result_pos, string_length, scratch1);
4144
  __ CopyBytes(string, result_pos, string_length, scratch);
4161 4145
  __ cmp(element, elements_end);
4162 4146
  __ b(lt, &one_char_separator_loop);  // End while (element < elements_end).
4163 4147
  ASSERT(result.is(r0));
......
4178 4162
  __ add(string,
4179 4163
         separator,
4180 4164
         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4181
  __ CopyBytes(string, result_pos, string_length, scratch1);
4165
  __ CopyBytes(string, result_pos, string_length, scratch);
4182 4166

  
4183 4167
  __ bind(&long_separator);
4184 4168
  __ ldr(string, MemOperand(element, kPointerSize, PostIndex));
......
4187 4171
  __ add(string,
4188 4172
         string,
4189 4173
         Operand(SeqOneByteString::kHeaderSize - kHeapObjectTag));
4190
  __ CopyBytes(string, result_pos, string_length, scratch1);
4174
  __ CopyBytes(string, result_pos, string_length, scratch);
4191 4175
  __ cmp(element, elements_end);
4192 4176
  __ b(lt, &long_separator_loop);  // End while (element < elements_end).
4193 4177
  ASSERT(result.is(r0));
......
4894 4878

  
4895 4879
#undef __
4896 4880

  
4881

  
4882
static const int32_t kBranchBeforeInterrupt =  0x5a000004;
4883

  
4884

  
4885
void BackEdgeTable::PatchAt(Code* unoptimized_code,
4886
                            Address pc,
4887
                            BackEdgeState target_state,
4888
                            Code* replacement_code) {
4889
  static const int kInstrSize = Assembler::kInstrSize;
4890
  Address branch_address = pc - 3 * kInstrSize;
4891
  CodePatcher patcher(branch_address, 1);
4892

  
4893
  switch (target_state) {
4894
    case INTERRUPT:
4895
      //  <decrement profiling counter>
4896
      //  2a 00 00 01       bpl ok
4897
      //  e5 9f c? ??       ldr ip, [pc, <interrupt stub address>]
4898
      //  e1 2f ff 3c       blx ip
4899
      //  ok-label
4900
      patcher.masm()->b(4 * kInstrSize, pl);  // Jump offset is 4 instructions.
4901
      ASSERT_EQ(kBranchBeforeInterrupt, Memory::int32_at(branch_address));
4902
      break;
4903
    case ON_STACK_REPLACEMENT:
4904
    case OSR_AFTER_STACK_CHECK:
4905
      //  <decrement profiling counter>
4906
      //  e1 a0 00 00       mov r0, r0 (NOP)
4907
      //  e5 9f c? ??       ldr ip, [pc, <on-stack replacement address>]
4908
      //  e1 2f ff 3c       blx ip
4909
      //  ok-label
4910
      patcher.masm()->nop();
4911
      break;
4912
  }
4913

  
4914
  Address pc_immediate_load_address = pc - 2 * kInstrSize;
4915
  // Replace the call address.
4916
  uint32_t interrupt_address_offset =
4917
      Memory::uint16_at(pc_immediate_load_address) & 0xfff;
4918
  Address interrupt_address_pointer = pc + interrupt_address_offset;
4919
  Memory::uint32_at(interrupt_address_pointer) =
4920
      reinterpret_cast<uint32_t>(replacement_code->entry());
4921

  
4922
  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
4923
      unoptimized_code, pc_immediate_load_address, replacement_code);
4924
}
4925

  
4926

  
4927
BackEdgeTable::BackEdgeState BackEdgeTable::GetBackEdgeState(
4928
    Isolate* isolate,
4929
    Code* unoptimized_code,
4930
    Address pc) {
4931
  static const int kInstrSize = Assembler::kInstrSize;
4932
  ASSERT(Memory::int32_at(pc - kInstrSize) == kBlxIp);
4933

  
4934
  Address branch_address = pc - 3 * kInstrSize;
4935
  Address pc_immediate_load_address = pc - 2 * kInstrSize;
4936
  uint32_t interrupt_address_offset =
4937
      Memory::uint16_at(pc_immediate_load_address) & 0xfff;
4938
  Address interrupt_address_pointer = pc + interrupt_address_offset;
4939

  
4940
  if (Memory::int32_at(branch_address) == kBranchBeforeInterrupt) {
4941
    ASSERT(Memory::uint32_at(interrupt_address_pointer) ==
4942
           reinterpret_cast<uint32_t>(
4943
               isolate->builtins()->InterruptCheck()->entry()));
4944
    ASSERT(Assembler::IsLdrPcImmediateOffset(
4945
               Assembler::instr_at(pc_immediate_load_address)));
4946
    return INTERRUPT;
4947
  }
4948

  
4949
  ASSERT(Assembler::IsNop(Assembler::instr_at(branch_address)));
4950
  ASSERT(Assembler::IsLdrPcImmediateOffset(
4951
             Assembler::instr_at(pc_immediate_load_address)));
4952

  
4953
  if (Memory::uint32_at(interrupt_address_pointer) ==
4954
      reinterpret_cast<uint32_t>(
4955
          isolate->builtins()->OnStackReplacement()->entry())) {
4956
    return ON_STACK_REPLACEMENT;
4957
  }
4958

  
4959
  ASSERT(Memory::uint32_at(interrupt_address_pointer) ==
4960
         reinterpret_cast<uint32_t>(
4961
             isolate->builtins()->OsrAfterStackCheck()->entry()));
4962
  return OSR_AFTER_STACK_CHECK;
4963
}
4964

  
4965

  
4897 4966
} }  // namespace v8::internal
4898 4967

  
4899 4968
#endif  // V8_TARGET_ARCH_ARM

Also available in: Unified diff