| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 19 matching lines...) Expand all Loading... |
| 30 #include "bootstrapper.h" | 30 #include "bootstrapper.h" |
| 31 #include "codegen-inl.h" | 31 #include "codegen-inl.h" |
| 32 #include "debug.h" | 32 #include "debug.h" |
| 33 #include "runtime.h" | 33 #include "runtime.h" |
| 34 | 34 |
| 35 namespace v8 { | 35 namespace v8 { |
| 36 namespace internal { | 36 namespace internal { |
| 37 | 37 |
| 38 MacroAssembler::MacroAssembler(void* buffer, int size) | 38 MacroAssembler::MacroAssembler(void* buffer, int size) |
| 39 : Assembler(buffer, size), | 39 : Assembler(buffer, size), |
| 40 unresolved_(0), | |
| 41 generating_stub_(false), | 40 generating_stub_(false), |
| 42 allow_stub_calls_(true), | 41 allow_stub_calls_(true), |
| 43 code_object_(Heap::undefined_value()) { | 42 code_object_(Heap::undefined_value()) { |
| 44 } | 43 } |
| 45 | 44 |
| 46 | 45 |
| 47 // We always generate arm code, never thumb code, even if V8 is compiled to | 46 // We always generate arm code, never thumb code, even if V8 is compiled to |
| 48 // thumb, so we require inter-working support | 47 // thumb, so we require inter-working support |
| 49 #if defined(__thumb__) && !defined(USE_THUMB_INTERWORK) | 48 #if defined(__thumb__) && !defined(USE_THUMB_INTERWORK) |
| 50 #error "flag -mthumb-interwork missing" | 49 #error "flag -mthumb-interwork missing" |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 // ip = sp + kPointerSize * #args; | 323 // ip = sp + kPointerSize * #args; |
| 325 add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); | 324 add(ip, sp, Operand(r0, LSL, kPointerSizeLog2)); |
| 326 | 325 |
| 327 // Align the stack at this point. After this point we have 5 pushes, | 326 // Align the stack at this point. After this point we have 5 pushes, |
| 328 // so in fact we have to unalign here! See also the assert on the | 327 // so in fact we have to unalign here! See also the assert on the |
| 329 // alignment in AlignStack. | 328 // alignment in AlignStack. |
| 330 AlignStack(1); | 329 AlignStack(1); |
| 331 | 330 |
| 332 // Push in reverse order: caller_fp, sp_on_exit, and caller_pc. | 331 // Push in reverse order: caller_fp, sp_on_exit, and caller_pc. |
| 333 stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); | 332 stm(db_w, sp, fp.bit() | ip.bit() | lr.bit()); |
| 334 mov(fp, Operand(sp)); // setup new frame pointer | 333 mov(fp, Operand(sp)); // Setup new frame pointer. |
| 335 | 334 |
| 336 if (mode == ExitFrame::MODE_DEBUG) { | 335 mov(ip, Operand(CodeObject())); |
| 337 mov(ip, Operand(Smi::FromInt(0))); | 336 push(ip); // Accessed from ExitFrame::code_slot. |
| 338 } else { | |
| 339 mov(ip, Operand(CodeObject())); | |
| 340 } | |
| 341 push(ip); | |
| 342 | 337 |
| 343 // Save the frame pointer and the context in top. | 338 // Save the frame pointer and the context in top. |
| 344 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); | 339 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address))); |
| 345 str(fp, MemOperand(ip)); | 340 str(fp, MemOperand(ip)); |
| 346 mov(ip, Operand(ExternalReference(Top::k_context_address))); | 341 mov(ip, Operand(ExternalReference(Top::k_context_address))); |
| 347 str(cp, MemOperand(ip)); | 342 str(cp, MemOperand(ip)); |
| 348 | 343 |
| 349 // Setup argc and the builtin function in callee-saved registers. | 344 // Setup argc and the builtin function in callee-saved registers. |
| 350 mov(r4, Operand(r0)); | 345 mov(r4, Operand(r0)); |
| 351 mov(r5, Operand(r1)); | 346 mov(r5, Operand(r1)); |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 SharedFunctionInfo::kFormalParameterCountOffset)); | 538 SharedFunctionInfo::kFormalParameterCountOffset)); |
| 544 ldr(code_reg, | 539 ldr(code_reg, |
| 545 MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag)); | 540 MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag)); |
| 546 add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); | 541 add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 547 | 542 |
| 548 ParameterCount expected(expected_reg); | 543 ParameterCount expected(expected_reg); |
| 549 InvokeCode(code_reg, expected, actual, flag); | 544 InvokeCode(code_reg, expected, actual, flag); |
| 550 } | 545 } |
| 551 | 546 |
| 552 | 547 |
| 548 void MacroAssembler::InvokeFunction(JSFunction* function, |
| 549 const ParameterCount& actual, |
| 550 InvokeFlag flag) { |
| 551 ASSERT(function->is_compiled()); |
| 552 |
| 553 // Get the function and setup the context. |
| 554 mov(r1, Operand(Handle<JSFunction>(function))); |
| 555 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 556 |
| 557 // Invoke the cached code. |
| 558 Handle<Code> code(function->code()); |
| 559 ParameterCount expected(function->shared()->formal_parameter_count()); |
| 560 InvokeCode(code, expected, actual, RelocInfo::CODE_TARGET, flag); |
| 561 } |
| 562 |
| 553 #ifdef ENABLE_DEBUGGER_SUPPORT | 563 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 554 void MacroAssembler::SaveRegistersToMemory(RegList regs) { | 564 void MacroAssembler::SaveRegistersToMemory(RegList regs) { |
| 555 ASSERT((regs & ~kJSCallerSaved) == 0); | 565 ASSERT((regs & ~kJSCallerSaved) == 0); |
| 556 // Copy the content of registers to memory location. | 566 // Copy the content of registers to memory location. |
| 557 for (int i = 0; i < kNumJSCallerSaved; i++) { | 567 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 558 int r = JSCallerSavedCode(i); | 568 int r = JSCallerSavedCode(i); |
| 559 if ((regs & (1 << r)) != 0) { | 569 if ((regs & (1 << r)) != 0) { |
| 560 Register reg = { r }; | 570 Register reg = { r }; |
| 561 mov(ip, Operand(ExternalReference(Debug_Address::Register(i)))); | 571 mov(ip, Operand(ExternalReference(Debug_Address::Register(i)))); |
| 562 str(reg, MemOperand(ip)); | 572 str(reg, MemOperand(ip)); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 // Copy the content of the stack to the memory location and adjust base. | 611 // Copy the content of the stack to the memory location and adjust base. |
| 602 for (int i = 0; i < kNumJSCallerSaved; i++) { | 612 for (int i = 0; i < kNumJSCallerSaved; i++) { |
| 603 int r = JSCallerSavedCode(i); | 613 int r = JSCallerSavedCode(i); |
| 604 if ((regs & (1 << r)) != 0) { | 614 if ((regs & (1 << r)) != 0) { |
| 605 mov(ip, Operand(ExternalReference(Debug_Address::Register(i)))); | 615 mov(ip, Operand(ExternalReference(Debug_Address::Register(i)))); |
| 606 ldr(scratch, MemOperand(base, 4, PostIndex)); | 616 ldr(scratch, MemOperand(base, 4, PostIndex)); |
| 607 str(scratch, MemOperand(ip)); | 617 str(scratch, MemOperand(ip)); |
| 608 } | 618 } |
| 609 } | 619 } |
| 610 } | 620 } |
| 621 |
| 622 |
| 623 void MacroAssembler::DebugBreak() { |
| 624 ASSERT(allow_stub_calls()); |
| 625 mov(r0, Operand(0)); |
| 626 mov(r1, Operand(ExternalReference(Runtime::kDebugBreak))); |
| 627 CEntryStub ces(1); |
| 628 Call(ces.GetCode(), RelocInfo::DEBUG_BREAK); |
| 629 } |
| 611 #endif | 630 #endif |
| 612 | 631 |
| 613 | 632 |
| 614 void MacroAssembler::PushTryHandler(CodeLocation try_location, | 633 void MacroAssembler::PushTryHandler(CodeLocation try_location, |
| 615 HandlerType type) { | 634 HandlerType type) { |
| 616 // Adjust this code if not the case. | 635 // Adjust this code if not the case. |
| 617 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 636 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
| 618 // The pc (return address) is passed in register lr. | 637 // The pc (return address) is passed in register lr. |
| 619 if (try_location == IN_JAVASCRIPT) { | 638 if (try_location == IN_JAVASCRIPT) { |
| 620 if (type == TRY_CATCH_HANDLER) { | 639 if (type == TRY_CATCH_HANDLER) { |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 CEntryStub stub(1); | 1217 CEntryStub stub(1); |
| 1199 CallStub(&stub); | 1218 CallStub(&stub); |
| 1200 } | 1219 } |
| 1201 | 1220 |
| 1202 | 1221 |
| 1203 void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) { | 1222 void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) { |
| 1204 CallRuntime(Runtime::FunctionForId(fid), num_arguments); | 1223 CallRuntime(Runtime::FunctionForId(fid), num_arguments); |
| 1205 } | 1224 } |
| 1206 | 1225 |
| 1207 | 1226 |
| 1227 void MacroAssembler::CallExternalReference(const ExternalReference& ext, |
| 1228 int num_arguments) { |
| 1229 mov(r0, Operand(num_arguments)); |
| 1230 mov(r1, Operand(ext)); |
| 1231 |
| 1232 CEntryStub stub(1); |
| 1233 CallStub(&stub); |
| 1234 } |
| 1235 |
| 1236 |
| 1208 void MacroAssembler::TailCallRuntime(const ExternalReference& ext, | 1237 void MacroAssembler::TailCallRuntime(const ExternalReference& ext, |
| 1209 int num_arguments, | 1238 int num_arguments, |
| 1210 int result_size) { | 1239 int result_size) { |
| 1211 // TODO(1236192): Most runtime routines don't need the number of | 1240 // TODO(1236192): Most runtime routines don't need the number of |
| 1212 // arguments passed in because it is constant. At some point we | 1241 // arguments passed in because it is constant. At some point we |
| 1213 // should remove this need and make the runtime routine entry code | 1242 // should remove this need and make the runtime routine entry code |
| 1214 // smarter. | 1243 // smarter. |
| 1215 mov(r0, Operand(num_arguments)); | 1244 mov(r0, Operand(num_arguments)); |
| 1216 JumpToRuntime(ext); | 1245 JumpToRuntime(ext); |
| 1217 } | 1246 } |
| 1218 | 1247 |
| 1219 | 1248 |
| 1220 void MacroAssembler::JumpToRuntime(const ExternalReference& builtin) { | 1249 void MacroAssembler::JumpToRuntime(const ExternalReference& builtin) { |
| 1221 #if defined(__thumb__) | 1250 #if defined(__thumb__) |
| 1222 // Thumb mode builtin. | 1251 // Thumb mode builtin. |
| 1223 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); | 1252 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); |
| 1224 #endif | 1253 #endif |
| 1225 mov(r1, Operand(builtin)); | 1254 mov(r1, Operand(builtin)); |
| 1226 CEntryStub stub(1); | 1255 CEntryStub stub(1); |
| 1227 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); | 1256 Jump(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 1228 } | 1257 } |
| 1229 | 1258 |
| 1230 | 1259 |
| 1231 Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id, | |
| 1232 bool* resolved) { | |
| 1233 // Contract with compiled functions is that the function is passed in r1. | |
| 1234 int builtins_offset = | |
| 1235 JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize); | |
| 1236 ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); | |
| 1237 ldr(r1, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); | |
| 1238 ldr(r1, FieldMemOperand(r1, builtins_offset)); | |
| 1239 | |
| 1240 return Builtins::GetCode(id, resolved); | |
| 1241 } | |
| 1242 | |
| 1243 | |
| 1244 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, | 1260 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, |
| 1245 InvokeJSFlags flags) { | 1261 InvokeJSFlags flags) { |
| 1246 bool resolved; | 1262 GetBuiltinEntry(r2, id); |
| 1247 Handle<Code> code = ResolveBuiltin(id, &resolved); | |
| 1248 | |
| 1249 if (flags == CALL_JS) { | 1263 if (flags == CALL_JS) { |
| 1250 Call(code, RelocInfo::CODE_TARGET); | 1264 Call(r2); |
| 1251 } else { | 1265 } else { |
| 1252 ASSERT(flags == JUMP_JS); | 1266 ASSERT(flags == JUMP_JS); |
| 1253 Jump(code, RelocInfo::CODE_TARGET); | 1267 Jump(r2); |
| 1254 } | |
| 1255 | |
| 1256 if (!resolved) { | |
| 1257 const char* name = Builtins::GetName(id); | |
| 1258 int argc = Builtins::GetArgumentsCount(id); | |
| 1259 uint32_t flags = | |
| 1260 Bootstrapper::FixupFlagsArgumentsCount::encode(argc) | | |
| 1261 Bootstrapper::FixupFlagsUseCodeObject::encode(false); | |
| 1262 Unresolved entry = { pc_offset() - kInstrSize, flags, name }; | |
| 1263 unresolved_.Add(entry); | |
| 1264 } | 1268 } |
| 1265 } | 1269 } |
| 1266 | 1270 |
| 1267 | 1271 |
| 1268 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { | 1272 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) { |
| 1269 bool resolved; | 1273 // Load the JavaScript builtin function from the builtins object. |
| 1270 Handle<Code> code = ResolveBuiltin(id, &resolved); | 1274 ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 1271 | 1275 ldr(r1, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset)); |
| 1272 mov(target, Operand(code)); | 1276 int builtins_offset = |
| 1273 if (!resolved) { | 1277 JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize); |
| 1274 const char* name = Builtins::GetName(id); | 1278 ldr(r1, FieldMemOperand(r1, builtins_offset)); |
| 1275 int argc = Builtins::GetArgumentsCount(id); | 1279 // Load the code entry point from the function into the target register. |
| 1276 uint32_t flags = | 1280 ldr(target, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1277 Bootstrapper::FixupFlagsArgumentsCount::encode(argc) | | 1281 ldr(target, FieldMemOperand(target, SharedFunctionInfo::kCodeOffset)); |
| 1278 Bootstrapper::FixupFlagsUseCodeObject::encode(true); | |
| 1279 Unresolved entry = { pc_offset() - kInstrSize, flags, name }; | |
| 1280 unresolved_.Add(entry); | |
| 1281 } | |
| 1282 | |
| 1283 add(target, target, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1282 add(target, target, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 1284 } | 1283 } |
| 1285 | 1284 |
| 1286 | 1285 |
| 1287 void MacroAssembler::SetCounter(StatsCounter* counter, int value, | 1286 void MacroAssembler::SetCounter(StatsCounter* counter, int value, |
| 1288 Register scratch1, Register scratch2) { | 1287 Register scratch1, Register scratch2) { |
| 1289 if (FLAG_native_code_counters && counter->Enabled()) { | 1288 if (FLAG_native_code_counters && counter->Enabled()) { |
| 1290 mov(scratch1, Operand(value)); | 1289 mov(scratch1, Operand(value)); |
| 1291 mov(scratch2, Operand(ExternalReference(counter))); | 1290 mov(scratch2, Operand(ExternalReference(counter))); |
| 1292 str(scratch1, MemOperand(scratch2)); | 1291 str(scratch1, MemOperand(scratch2)); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 } | 1467 } |
| 1469 | 1468 |
| 1470 | 1469 |
| 1471 void CodePatcher::Emit(Address addr) { | 1470 void CodePatcher::Emit(Address addr) { |
| 1472 masm()->emit(reinterpret_cast<Instr>(addr)); | 1471 masm()->emit(reinterpret_cast<Instr>(addr)); |
| 1473 } | 1472 } |
| 1474 #endif // ENABLE_DEBUGGER_SUPPORT | 1473 #endif // ENABLE_DEBUGGER_SUPPORT |
| 1475 | 1474 |
| 1476 | 1475 |
| 1477 } } // namespace v8::internal | 1476 } } // namespace v8::internal |
| OLD | NEW |