| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 17 matching lines...) Expand all Loading... |
| 28 #include <limits.h> // For LONG_MIN, LONG_MAX. | 28 #include <limits.h> // For LONG_MIN, LONG_MAX. |
| 29 | 29 |
| 30 #include "v8.h" | 30 #include "v8.h" |
| 31 | 31 |
| 32 #if V8_TARGET_ARCH_ARM | 32 #if V8_TARGET_ARCH_ARM |
| 33 | 33 |
| 34 #include "bootstrapper.h" | 34 #include "bootstrapper.h" |
| 35 #include "codegen.h" | 35 #include "codegen.h" |
| 36 #include "cpu-profiler.h" | 36 #include "cpu-profiler.h" |
| 37 #include "debug.h" | 37 #include "debug.h" |
| 38 #include "isolate-inl.h" |
| 38 #include "runtime.h" | 39 #include "runtime.h" |
| 39 | 40 |
| 40 namespace v8 { | 41 namespace v8 { |
| 41 namespace internal { | 42 namespace internal { |
| 42 | 43 |
| 43 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size) | 44 MacroAssembler::MacroAssembler(Isolate* arg_isolate, void* buffer, int size) |
| 44 : Assembler(arg_isolate, buffer, size), | 45 : Assembler(arg_isolate, buffer, size), |
| 45 generating_stub_(false), | 46 generating_stub_(false), |
| 46 allow_stub_calls_(true), | 47 allow_stub_calls_(true), |
| 47 has_frame_(false) { | 48 has_frame_(false) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 227 } |
| 227 | 228 |
| 228 | 229 |
| 229 void MacroAssembler::Push(Handle<Object> handle) { | 230 void MacroAssembler::Push(Handle<Object> handle) { |
| 230 mov(ip, Operand(handle)); | 231 mov(ip, Operand(handle)); |
| 231 push(ip); | 232 push(ip); |
| 232 } | 233 } |
| 233 | 234 |
| 234 | 235 |
| 235 void MacroAssembler::Move(Register dst, Handle<Object> value) { | 236 void MacroAssembler::Move(Register dst, Handle<Object> value) { |
| 236 mov(dst, Operand(value)); | 237 AllowDeferredHandleDereference smi_check; |
| 238 if (value->IsSmi()) { |
| 239 mov(dst, Operand(value)); |
| 240 } else { |
| 241 ASSERT(value->IsHeapObject()); |
| 242 if (isolate()->heap()->InNewSpace(*value)) { |
| 243 Handle<Cell> cell = isolate()->factory()->NewCell(value); |
| 244 mov(dst, Operand(cell)); |
| 245 ldr(dst, FieldMemOperand(dst, Cell::kValueOffset)); |
| 246 } else { |
| 247 mov(dst, Operand(value)); |
| 248 } |
| 249 } |
| 237 } | 250 } |
| 238 | 251 |
| 239 | 252 |
| 240 void MacroAssembler::Move(Register dst, Register src, Condition cond) { | 253 void MacroAssembler::Move(Register dst, Register src, Condition cond) { |
| 241 if (!dst.is(src)) { | 254 if (!dst.is(src)) { |
| 242 mov(dst, src, LeaveCC, cond); | 255 mov(dst, src, LeaveCC, cond); |
| 243 } | 256 } |
| 244 } | 257 } |
| 245 | 258 |
| 246 | 259 |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 b(eq, &done); | 377 b(eq, &done); |
| 365 mov(dst, Operand::Zero(), LeaveCC, mi); // 0 if negative. | 378 mov(dst, Operand::Zero(), LeaveCC, mi); // 0 if negative. |
| 366 mov(dst, Operand(satval), LeaveCC, pl); // satval if positive. | 379 mov(dst, Operand(satval), LeaveCC, pl); // satval if positive. |
| 367 bind(&done); | 380 bind(&done); |
| 368 } else { | 381 } else { |
| 369 usat(dst, satpos, src, cond); | 382 usat(dst, satpos, src, cond); |
| 370 } | 383 } |
| 371 } | 384 } |
| 372 | 385 |
| 373 | 386 |
| 387 void MacroAssembler::Load(Register dst, |
| 388 const MemOperand& src, |
| 389 Representation r) { |
| 390 ASSERT(!r.IsDouble()); |
| 391 if (r.IsInteger8()) { |
| 392 ldrsb(dst, src); |
| 393 } else if (r.IsUInteger8()) { |
| 394 ldrb(dst, src); |
| 395 } else if (r.IsInteger16()) { |
| 396 ldrsh(dst, src); |
| 397 } else if (r.IsUInteger16()) { |
| 398 ldrh(dst, src); |
| 399 } else { |
| 400 ldr(dst, src); |
| 401 } |
| 402 } |
| 403 |
| 404 |
| 405 void MacroAssembler::Store(Register src, |
| 406 const MemOperand& dst, |
| 407 Representation r) { |
| 408 ASSERT(!r.IsDouble()); |
| 409 if (r.IsInteger8() || r.IsUInteger8()) { |
| 410 strb(src, dst); |
| 411 } else if (r.IsInteger16() || r.IsUInteger16()) { |
| 412 strh(src, dst); |
| 413 } else { |
| 414 str(src, dst); |
| 415 } |
| 416 } |
| 417 |
| 418 |
| 374 void MacroAssembler::LoadRoot(Register destination, | 419 void MacroAssembler::LoadRoot(Register destination, |
| 375 Heap::RootListIndex index, | 420 Heap::RootListIndex index, |
| 376 Condition cond) { | 421 Condition cond) { |
| 377 if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && | 422 if (CpuFeatures::IsSupported(MOVW_MOVT_IMMEDIATE_LOADS) && |
| 378 isolate()->heap()->RootCanBeTreatedAsConstant(index) && | 423 isolate()->heap()->RootCanBeTreatedAsConstant(index) && |
| 379 !predictable_code_size()) { | 424 !predictable_code_size()) { |
| 380 // The CPU supports fast immediate values, and this root will never | 425 // The CPU supports fast immediate values, and this root will never |
| 381 // change. We will load it as a relocatable immediate value. | 426 // change. We will load it as a relocatable immediate value. |
| 382 Handle<Object> root(&isolate()->heap()->roots_array_start()[index]); | 427 Handle<Object> root(&isolate()->heap()->roots_array_start()[index]); |
| 383 mov(destination, Operand(root), LeaveCC, cond); | 428 mov(destination, Operand(root), LeaveCC, cond); |
| 384 return; | 429 return; |
| 385 } | 430 } |
| 386 ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); | 431 ldr(destination, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); |
| 387 } | 432 } |
| 388 | 433 |
| 389 | 434 |
| 390 void MacroAssembler::StoreRoot(Register source, | 435 void MacroAssembler::StoreRoot(Register source, |
| 391 Heap::RootListIndex index, | 436 Heap::RootListIndex index, |
| 392 Condition cond) { | 437 Condition cond) { |
| 393 str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); | 438 str(source, MemOperand(kRootRegister, index << kPointerSizeLog2), cond); |
| 394 } | 439 } |
| 395 | 440 |
| 396 | 441 |
| 397 void MacroAssembler::LoadHeapObject(Register result, | |
| 398 Handle<HeapObject> object) { | |
| 399 AllowDeferredHandleDereference using_raw_address; | |
| 400 if (isolate()->heap()->InNewSpace(*object)) { | |
| 401 Handle<Cell> cell = isolate()->factory()->NewCell(object); | |
| 402 mov(result, Operand(cell)); | |
| 403 ldr(result, FieldMemOperand(result, Cell::kValueOffset)); | |
| 404 } else { | |
| 405 mov(result, Operand(object)); | |
| 406 } | |
| 407 } | |
| 408 | |
| 409 | |
| 410 void MacroAssembler::InNewSpace(Register object, | 442 void MacroAssembler::InNewSpace(Register object, |
| 411 Register scratch, | 443 Register scratch, |
| 412 Condition cond, | 444 Condition cond, |
| 413 Label* branch) { | 445 Label* branch) { |
| 414 ASSERT(cond == eq || cond == ne); | 446 ASSERT(cond == eq || cond == ne); |
| 415 and_(scratch, object, Operand(ExternalReference::new_space_mask(isolate()))); | 447 and_(scratch, object, Operand(ExternalReference::new_space_mask(isolate()))); |
| 416 cmp(scratch, Operand(ExternalReference::new_space_start(isolate()))); | 448 cmp(scratch, Operand(ExternalReference::new_space_start(isolate()))); |
| 417 b(cond, branch); | 449 b(cond, branch); |
| 418 } | 450 } |
| 419 | 451 |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 if (frame_mode == BUILD_STUB_FRAME) { | 952 if (frame_mode == BUILD_STUB_FRAME) { |
| 921 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 953 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 922 Push(Smi::FromInt(StackFrame::STUB)); | 954 Push(Smi::FromInt(StackFrame::STUB)); |
| 923 // Adjust FP to point to saved FP. | 955 // Adjust FP to point to saved FP. |
| 924 add(fp, sp, Operand(2 * kPointerSize)); | 956 add(fp, sp, Operand(2 * kPointerSize)); |
| 925 } else { | 957 } else { |
| 926 PredictableCodeSizeScope predictible_code_size_scope( | 958 PredictableCodeSizeScope predictible_code_size_scope( |
| 927 this, kNoCodeAgeSequenceLength * Assembler::kInstrSize); | 959 this, kNoCodeAgeSequenceLength * Assembler::kInstrSize); |
| 928 // The following three instructions must remain together and unmodified | 960 // The following three instructions must remain together and unmodified |
| 929 // for code aging to work properly. | 961 // for code aging to work properly. |
| 930 if (FLAG_optimize_for_size && FLAG_age_code) { | 962 if (isolate()->IsCodePreAgingActive()) { |
| 931 // Pre-age the code. | 963 // Pre-age the code. |
| 932 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); | 964 Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); |
| 933 add(r0, pc, Operand(-8)); | 965 add(r0, pc, Operand(-8)); |
| 934 ldr(pc, MemOperand(pc, -4)); | 966 ldr(pc, MemOperand(pc, -4)); |
| 935 dd(reinterpret_cast<uint32_t>(stub->instruction_start())); | 967 emit_code_stub_address(stub); |
| 936 } else { | 968 } else { |
| 937 stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 969 stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
| 938 nop(ip.code()); | 970 nop(ip.code()); |
| 939 // Adjust FP to point to saved FP. | 971 // Adjust FP to point to saved FP. |
| 940 add(fp, sp, Operand(2 * kPointerSize)); | 972 add(fp, sp, Operand(2 * kPointerSize)); |
| 941 } | 973 } |
| 942 } | 974 } |
| 943 } | 975 } |
| 944 | 976 |
| 945 | 977 |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1278 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, | 1310 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
| 1279 const ParameterCount& expected, | 1311 const ParameterCount& expected, |
| 1280 const ParameterCount& actual, | 1312 const ParameterCount& actual, |
| 1281 InvokeFlag flag, | 1313 InvokeFlag flag, |
| 1282 const CallWrapper& call_wrapper, | 1314 const CallWrapper& call_wrapper, |
| 1283 CallKind call_kind) { | 1315 CallKind call_kind) { |
| 1284 // You can't call a function without a valid frame. | 1316 // You can't call a function without a valid frame. |
| 1285 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 1317 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
| 1286 | 1318 |
| 1287 // Get the function and setup the context. | 1319 // Get the function and setup the context. |
| 1288 LoadHeapObject(r1, function); | 1320 Move(r1, function); |
| 1289 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1321 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 1290 | 1322 |
| 1291 // We call indirectly through the code field in the function to | 1323 // We call indirectly through the code field in the function to |
| 1292 // allow recompilation to take effect without changing any of the | 1324 // allow recompilation to take effect without changing any of the |
| 1293 // call sites. | 1325 // call sites. |
| 1294 ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); | 1326 ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset)); |
| 1295 InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind); | 1327 InvokeCode(r3, expected, actual, flag, call_wrapper, call_kind); |
| 1296 } | 1328 } |
| 1297 | 1329 |
| 1298 | 1330 |
| (...skipping 2623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3922 for (int i = 0; i < Register::NumAllocatableRegisters(); i++) { | 3954 for (int i = 0; i < Register::NumAllocatableRegisters(); i++) { |
| 3923 Register candidate = Register::FromAllocationIndex(i); | 3955 Register candidate = Register::FromAllocationIndex(i); |
| 3924 if (regs & candidate.bit()) continue; | 3956 if (regs & candidate.bit()) continue; |
| 3925 return candidate; | 3957 return candidate; |
| 3926 } | 3958 } |
| 3927 UNREACHABLE(); | 3959 UNREACHABLE(); |
| 3928 return no_reg; | 3960 return no_reg; |
| 3929 } | 3961 } |
| 3930 | 3962 |
| 3931 | 3963 |
| 3964 void MacroAssembler::JumpIfDictionaryInPrototypeChain( |
| 3965 Register object, |
| 3966 Register scratch0, |
| 3967 Register scratch1, |
| 3968 Label* found) { |
| 3969 ASSERT(!scratch1.is(scratch0)); |
| 3970 Factory* factory = isolate()->factory(); |
| 3971 Register current = scratch0; |
| 3972 Label loop_again; |
| 3973 |
| 3974 // scratch contained elements pointer. |
| 3975 mov(current, object); |
| 3976 |
| 3977 // Loop based on the map going up the prototype chain. |
| 3978 bind(&loop_again); |
| 3979 ldr(current, FieldMemOperand(current, HeapObject::kMapOffset)); |
| 3980 ldr(scratch1, FieldMemOperand(current, Map::kBitField2Offset)); |
| 3981 Ubfx(scratch1, scratch1, Map::kElementsKindShift, Map::kElementsKindBitCount); |
| 3982 cmp(scratch1, Operand(DICTIONARY_ELEMENTS)); |
| 3983 b(eq, found); |
| 3984 ldr(current, FieldMemOperand(current, Map::kPrototypeOffset)); |
| 3985 cmp(current, Operand(factory->null_value())); |
| 3986 b(ne, &loop_again); |
| 3987 } |
| 3988 |
| 3989 |
| 3932 #ifdef DEBUG | 3990 #ifdef DEBUG |
| 3933 bool AreAliased(Register reg1, | 3991 bool AreAliased(Register reg1, |
| 3934 Register reg2, | 3992 Register reg2, |
| 3935 Register reg3, | 3993 Register reg3, |
| 3936 Register reg4, | 3994 Register reg4, |
| 3937 Register reg5, | 3995 Register reg5, |
| 3938 Register reg6) { | 3996 Register reg6) { |
| 3939 int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() + | 3997 int n_of_valid_regs = reg1.is_valid() + reg2.is_valid() + |
| 3940 reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid(); | 3998 reg3.is_valid() + reg4.is_valid() + reg5.is_valid() + reg6.is_valid(); |
| 3941 | 3999 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3992 void CodePatcher::EmitCondition(Condition cond) { | 4050 void CodePatcher::EmitCondition(Condition cond) { |
| 3993 Instr instr = Assembler::instr_at(masm_.pc_); | 4051 Instr instr = Assembler::instr_at(masm_.pc_); |
| 3994 instr = (instr & ~kCondMask) | cond; | 4052 instr = (instr & ~kCondMask) | cond; |
| 3995 masm_.emit(instr); | 4053 masm_.emit(instr); |
| 3996 } | 4054 } |
| 3997 | 4055 |
| 3998 | 4056 |
| 3999 } } // namespace v8::internal | 4057 } } // namespace v8::internal |
| 4000 | 4058 |
| 4001 #endif // V8_TARGET_ARCH_ARM | 4059 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |