00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "bootstrapper.h"
00031 #include "codegen-inl.h"
00032 #include "debug.h"
00033 #include "runtime.h"
00034
00035 namespace v8 { namespace internal {
00036
00037
00038 Register cp = { 8 };
00039 Register pp = { 10 };
00040
00041
00042 MacroAssembler::MacroAssembler(void* buffer, int size)
00043 : Assembler(buffer, size),
00044 unresolved_(0),
00045 generating_stub_(false),
00046 allow_stub_calls_(true) {
00047 }
00048
00049
00050
00051
00052 #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
00053 #error "flag -mthumb-interwork missing"
00054 #endif
00055
00056
00057
00058
00059 #if defined(__THUMB_INTERWORK__)
00060 #if !defined(__ARM_ARCH_5T__) && !defined(__ARM_ARCH_5TE__)
00061
00062 #error "for thumb inter-working we require architecture v5t or above"
00063 #endif
00064 #endif
00065
00066
00067
00068 #if defined(__THUMB_INTERWORK__) || defined(__ARM_ARCH_5__)
00069 #define USE_BLX 1
00070 #endif
00071
00072
00073 #if defined(__THUMB_INTERWORK__)
00074 #define USE_BX 1
00075 #endif
00076
00077
00078 void MacroAssembler::Jump(Register target, Condition cond) {
00079 #if USE_BX
00080 bx(target, cond);
00081 #else
00082 mov(pc, Operand(target), LeaveCC, cond);
00083 #endif
00084 }
00085
00086
00087 void MacroAssembler::Jump(intptr_t target, RelocInfo::Mode rmode,
00088 Condition cond) {
00089 #if USE_BX
00090 mov(ip, Operand(target, rmode), LeaveCC, cond);
00091 bx(ip, cond);
00092 #else
00093 mov(pc, Operand(target, rmode), LeaveCC, cond);
00094 #endif
00095 }
00096
00097
00098 void MacroAssembler::Jump(byte* target, RelocInfo::Mode rmode,
00099 Condition cond) {
00100 ASSERT(!RelocInfo::IsCodeTarget(rmode));
00101 Jump(reinterpret_cast<intptr_t>(target), rmode, cond);
00102 }
00103
00104
00105 void MacroAssembler::Jump(Handle<Code> code, RelocInfo::Mode rmode,
00106 Condition cond) {
00107 ASSERT(RelocInfo::IsCodeTarget(rmode));
00108
00109 Jump(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
00110 }
00111
00112
00113 void MacroAssembler::Call(Register target, Condition cond) {
00114 #if USE_BLX
00115 blx(target, cond);
00116 #else
00117
00118 mov(lr, Operand(pc), LeaveCC, cond);
00119 mov(pc, Operand(target), LeaveCC, cond);
00120 #endif
00121 }
00122
00123
00124 void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
00125 Condition cond) {
00126 #if !defined(__arm__)
00127 if (rmode == RelocInfo::RUNTIME_ENTRY) {
00128 mov(r2, Operand(target, rmode), LeaveCC, cond);
00129
00130 mov(lr, Operand(pc), LeaveCC, cond);
00131
00132
00133 swi(assembler::arm::call_rt_r2);
00134 } else {
00135
00136 mov(lr, Operand(pc), LeaveCC, cond);
00137
00138 mov(pc, Operand(target, rmode), LeaveCC, cond);
00139 }
00140 #else
00141
00142 mov(lr, Operand(pc), LeaveCC, cond);
00143
00144 mov(pc, Operand(target, rmode), LeaveCC, cond);
00145 #endif // !defined(__arm__)
00146
00147
00148
00149
00150
00151 ASSERT(kTargetAddrToReturnAddrDist == sizeof(Instr));
00152 }
00153
00154
00155 void MacroAssembler::Call(byte* target, RelocInfo::Mode rmode,
00156 Condition cond) {
00157 ASSERT(!RelocInfo::IsCodeTarget(rmode));
00158 Call(reinterpret_cast<intptr_t>(target), rmode, cond);
00159 }
00160
00161
00162 void MacroAssembler::Call(Handle<Code> code, RelocInfo::Mode rmode,
00163 Condition cond) {
00164 ASSERT(RelocInfo::IsCodeTarget(rmode));
00165
00166 Call(reinterpret_cast<intptr_t>(code.location()), rmode, cond);
00167 }
00168
00169
00170 void MacroAssembler::Ret() {
00171 #if USE_BX
00172 bx(lr);
00173 #else
00174 mov(pc, Operand(lr));
00175 #endif
00176 }
00177
00178
00179
00180
00181
00182 void MacroAssembler::RecordWrite(Register object, Register offset,
00183 Register scratch) {
00184
00185
00186
00187 const int kRSetWordShift = 3;
00188
00189 Label fast, done;
00190
00191
00192
00193
00194
00195 and_(scratch, object, Operand(Heap::NewSpaceMask()));
00196 cmp(scratch, Operand(ExternalReference::new_space_start()));
00197 b(eq, &done);
00198
00199
00200
00201
00202 mov(ip, Operand(Page::kPageAlignmentMask));
00203 and_(scratch, object, Operand(ip));
00204 add(offset, scratch, Operand(offset));
00205 mov(offset, Operand(offset, LSR, kObjectAlignmentBits));
00206
00207
00208
00209
00210 bic(object, object, Operand(ip));
00211
00212
00213
00214
00215
00216 cmp(offset, Operand(Page::kPageSize / kPointerSize));
00217 b(lt, &fast);
00218
00219
00220
00221
00222 sub(offset, offset, Operand(Page::kPageSize / kPointerSize));
00223
00224
00225 ldr(scratch, MemOperand(object, Page::kObjectStartOffset
00226 + FixedArray::kLengthOffset));
00227 mov(scratch, Operand(scratch, LSL, kObjectAlignmentBits));
00228
00229
00230 add(object, object, Operand(Page::kObjectStartOffset
00231 + Array::kHeaderSize));
00232 add(object, object, Operand(scratch));
00233
00234 bind(&fast);
00235
00236
00237
00238 bic(scratch, offset, Operand(kBitsPerInt - 1));
00239 add(object, object, Operand(scratch, LSR, kRSetWordShift));
00240
00241
00242
00243 and_(offset, offset, Operand(kBitsPerInt - 1));
00244
00245 ldr(scratch, MemOperand(object));
00246 mov(ip, Operand(1));
00247 orr(scratch, scratch, Operand(ip, LSL, offset));
00248 str(scratch, MemOperand(object));
00249
00250 bind(&done);
00251 }
00252
00253
00254 void MacroAssembler::EnterFrame(StackFrame::Type type) {
00255
00256 stm(db_w, sp, cp.bit() | fp.bit() | lr.bit());
00257 mov(ip, Operand(Smi::FromInt(type)));
00258 push(ip);
00259 mov(ip, Operand(0));
00260 push(ip);
00261 add(fp, sp, Operand(3 * kPointerSize));
00262 }
00263
00264
00265 void MacroAssembler::LeaveFrame(StackFrame::Type type) {
00266
00267
00268
00269
00270
00271
00272 mov(sp, fp);
00273 ldm(ia_w, sp, fp.bit() | lr.bit());
00274 }
00275
00276
00277 void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
00278 ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
00279
00280
00281
00282
00283
00284 add(ip, sp, Operand(r0, LSL, kPointerSizeLog2));
00285
00286
00287 stm(db_w, sp, fp.bit() | ip.bit() | lr.bit());
00288 mov(fp, Operand(sp));
00289
00290
00291 mov(ip, Operand(type == StackFrame::EXIT_DEBUG ? 1 : 0));
00292 push(ip);
00293
00294
00295 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
00296 str(fp, MemOperand(ip));
00297 mov(ip, Operand(ExternalReference(Top::k_context_address)));
00298 str(cp, MemOperand(ip));
00299
00300
00301 mov(r4, Operand(r0));
00302 mov(r5, Operand(r1));
00303
00304
00305 add(r6, fp, Operand(r4, LSL, kPointerSizeLog2));
00306 add(r6, r6, Operand(ExitFrameConstants::kPPDisplacement - kPointerSize));
00307
00308
00309
00310 if (type == StackFrame::EXIT_DEBUG) {
00311
00312 CopyRegistersFromMemoryToStack(sp, kJSCallerSaved);
00313 }
00314 }
00315
00316
00317 void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
00318
00319
00320 if (type == StackFrame::EXIT_DEBUG) {
00321
00322 const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
00323 const int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
00324 add(r3, fp, Operand(kOffset));
00325 CopyRegistersFromStackToMemory(r3, r2, kJSCallerSaved);
00326 }
00327
00328
00329 mov(r3, Operand(0));
00330 mov(ip, Operand(ExternalReference(Top::k_c_entry_fp_address)));
00331 str(r3, MemOperand(ip));
00332
00333
00334 mov(ip, Operand(ExternalReference(Top::k_context_address)));
00335 ldr(cp, MemOperand(ip));
00336 if (kDebug) {
00337 str(r3, MemOperand(ip));
00338 }
00339
00340
00341 mov(sp, Operand(fp));
00342 ldm(ia, sp, fp.bit() | sp.bit() | pc.bit());
00343 }
00344
00345
00346 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
00347 const ParameterCount& actual,
00348 Handle<Code> code_constant,
00349 Register code_reg,
00350 Label* done,
00351 InvokeFlag flag) {
00352 bool definitely_matches = false;
00353 Label regular_invoke;
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 ASSERT(actual.is_immediate() || actual.reg().is(r0));
00366 ASSERT(expected.is_immediate() || expected.reg().is(r2));
00367 ASSERT((!code_constant.is_null() && code_reg.is(no_reg)) || code_reg.is(r3));
00368
00369 if (expected.is_immediate()) {
00370 ASSERT(actual.is_immediate());
00371 if (expected.immediate() == actual.immediate()) {
00372 definitely_matches = true;
00373 } else {
00374 mov(r0, Operand(actual.immediate()));
00375 const int sentinel = SharedFunctionInfo::kDontAdaptArgumentsSentinel;
00376 if (expected.immediate() == sentinel) {
00377
00378
00379
00380
00381 definitely_matches = true;
00382 } else {
00383 mov(r2, Operand(expected.immediate()));
00384 }
00385 }
00386 } else {
00387 if (actual.is_immediate()) {
00388 cmp(expected.reg(), Operand(actual.immediate()));
00389 b(eq, ®ular_invoke);
00390 mov(r0, Operand(actual.immediate()));
00391 } else {
00392 cmp(expected.reg(), Operand(actual.reg()));
00393 b(eq, ®ular_invoke);
00394 }
00395 }
00396
00397 if (!definitely_matches) {
00398 if (!code_constant.is_null()) {
00399 mov(r3, Operand(code_constant));
00400 add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
00401 }
00402
00403 Handle<Code> adaptor =
00404 Handle<Code>(Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline));
00405 if (flag == CALL_FUNCTION) {
00406 Call(adaptor, RelocInfo::CODE_TARGET);
00407 b(done);
00408 } else {
00409 Jump(adaptor, RelocInfo::CODE_TARGET);
00410 }
00411 bind(®ular_invoke);
00412 }
00413 }
00414
00415
00416 void MacroAssembler::InvokeCode(Register code,
00417 const ParameterCount& expected,
00418 const ParameterCount& actual,
00419 InvokeFlag flag) {
00420 Label done;
00421
00422 InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);
00423 if (flag == CALL_FUNCTION) {
00424 Call(code);
00425 } else {
00426 ASSERT(flag == JUMP_FUNCTION);
00427 Jump(code);
00428 }
00429
00430
00431
00432 bind(&done);
00433 }
00434
00435
00436 void MacroAssembler::InvokeCode(Handle<Code> code,
00437 const ParameterCount& expected,
00438 const ParameterCount& actual,
00439 RelocInfo::Mode rmode,
00440 InvokeFlag flag) {
00441 Label done;
00442
00443 InvokePrologue(expected, actual, code, no_reg, &done, flag);
00444 if (flag == CALL_FUNCTION) {
00445 Call(code, rmode);
00446 } else {
00447 Jump(code, rmode);
00448 }
00449
00450
00451
00452 bind(&done);
00453 }
00454
00455
00456 void MacroAssembler::InvokeFunction(Register fun,
00457 const ParameterCount& actual,
00458 InvokeFlag flag) {
00459
00460 ASSERT(fun.is(r1));
00461
00462 Register expected_reg = r2;
00463 Register code_reg = r3;
00464
00465 ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
00466 ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
00467 ldr(expected_reg,
00468 FieldMemOperand(code_reg,
00469 SharedFunctionInfo::kFormalParameterCountOffset));
00470 ldr(code_reg,
00471 MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
00472 add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
00473
00474 ParameterCount expected(expected_reg);
00475 InvokeCode(code_reg, expected, actual, flag);
00476 }
00477
00478
00479 void MacroAssembler::SaveRegistersToMemory(RegList regs) {
00480 ASSERT((regs & ~kJSCallerSaved) == 0);
00481
00482 for (int i = 0; i < kNumJSCallerSaved; i++) {
00483 int r = JSCallerSavedCode(i);
00484 if ((regs & (1 << r)) != 0) {
00485 Register reg = { r };
00486 mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));
00487 str(reg, MemOperand(ip));
00488 }
00489 }
00490 }
00491
00492
00493 void MacroAssembler::RestoreRegistersFromMemory(RegList regs) {
00494 ASSERT((regs & ~kJSCallerSaved) == 0);
00495
00496 for (int i = kNumJSCallerSaved; --i >= 0;) {
00497 int r = JSCallerSavedCode(i);
00498 if ((regs & (1 << r)) != 0) {
00499 Register reg = { r };
00500 mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));
00501 ldr(reg, MemOperand(ip));
00502 }
00503 }
00504 }
00505
00506
00507 void MacroAssembler::CopyRegistersFromMemoryToStack(Register base,
00508 RegList regs) {
00509 ASSERT((regs & ~kJSCallerSaved) == 0);
00510
00511 for (int i = kNumJSCallerSaved; --i >= 0;) {
00512 int r = JSCallerSavedCode(i);
00513 if ((regs & (1 << r)) != 0) {
00514 mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));
00515 ldr(ip, MemOperand(ip));
00516 str(ip, MemOperand(base, 4, NegPreIndex));
00517 }
00518 }
00519 }
00520
00521
00522 void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
00523 Register scratch,
00524 RegList regs) {
00525 ASSERT((regs & ~kJSCallerSaved) == 0);
00526
00527 for (int i = 0; i < kNumJSCallerSaved; i++) {
00528 int r = JSCallerSavedCode(i);
00529 if ((regs & (1 << r)) != 0) {
00530 mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));
00531 ldr(scratch, MemOperand(base, 4, PostIndex));
00532 str(scratch, MemOperand(ip));
00533 }
00534 }
00535 }
00536
00537
00538 void MacroAssembler::PushTryHandler(CodeLocation try_location,
00539 HandlerType type) {
00540 ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize);
00541
00542 if (try_location == IN_JAVASCRIPT) {
00543 stm(db_w, sp, pp.bit() | fp.bit() | lr.bit());
00544 if (type == TRY_CATCH_HANDLER) {
00545 mov(r3, Operand(StackHandler::TRY_CATCH));
00546 } else {
00547 mov(r3, Operand(StackHandler::TRY_FINALLY));
00548 }
00549 push(r3);
00550 mov(r3, Operand(ExternalReference(Top::k_handler_address)));
00551 ldr(r1, MemOperand(r3));
00552 push(r1);
00553 str(sp, MemOperand(r3));
00554 mov(r0, Operand(Smi::FromInt(StackHandler::kCodeNotPresent)));
00555 push(r0);
00556 } else {
00557
00558 ASSERT(try_location == IN_JS_ENTRY);
00559
00560
00561
00562 mov(pp, Operand(0));
00563 mov(ip, Operand(0));
00564 stm(db_w, sp, pp.bit() | ip.bit() | lr.bit());
00565 mov(r6, Operand(StackHandler::ENTRY));
00566 push(r6);
00567 mov(r7, Operand(ExternalReference(Top::k_handler_address)));
00568 ldr(r6, MemOperand(r7));
00569 push(r6);
00570 str(sp, MemOperand(r7));
00571 mov(r5, Operand(Smi::FromInt(StackHandler::kCodeNotPresent)));
00572 push(r5);
00573 }
00574 }
00575
00576
00577 Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,
00578 JSObject* holder, Register holder_reg,
00579 Register scratch,
00580 Label* miss) {
00581
00582
00583 ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg));
00584
00585
00586 Register reg = object_reg;
00587 int depth = 1;
00588
00589
00590
00591 while (object != holder) {
00592 depth++;
00593
00594
00595
00596 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
00597
00598
00599 ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
00600 cmp(scratch, Operand(Handle<Map>(object->map())));
00601
00602
00603 b(ne, miss);
00604
00605
00606
00607
00608 if (object->IsJSGlobalProxy()) {
00609 CheckAccessGlobalProxy(reg, scratch, miss);
00610
00611
00612
00613 ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
00614 }
00615
00616 reg = holder_reg;
00617 JSObject* prototype = JSObject::cast(object->GetPrototype());
00618 if (Heap::InNewSpace(prototype)) {
00619
00620
00621 ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset));
00622 } else {
00623
00624 mov(reg, Operand(Handle<JSObject>(prototype)));
00625 }
00626
00627
00628 object = prototype;
00629 }
00630
00631
00632 ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));
00633 cmp(scratch, Operand(Handle<Map>(object->map())));
00634 b(ne, miss);
00635
00636
00637 LOG(IntEvent("check-maps-depth", depth));
00638
00639
00640
00641 ASSERT(object == holder);
00642 ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
00643 if (object->IsJSGlobalProxy()) {
00644 CheckAccessGlobalProxy(reg, scratch, miss);
00645 }
00646 return reg;
00647 }
00648
00649
00650 void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
00651 Register scratch,
00652 Label* miss) {
00653 Label same_contexts;
00654
00655 ASSERT(!holder_reg.is(scratch));
00656 ASSERT(!holder_reg.is(ip));
00657 ASSERT(!scratch.is(ip));
00658
00659
00660 ldr(scratch, MemOperand(fp, StandardFrameConstants::kContextOffset));
00661
00662 if (kDebug) {
00663 cmp(scratch, Operand(0));
00664 Check(ne, "we should not have an empty lexical context");
00665 }
00666
00667
00668 int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
00669 ldr(scratch, FieldMemOperand(scratch, offset));
00670 ldr(scratch, FieldMemOperand(scratch, GlobalObject::kGlobalContextOffset));
00671
00672
00673 if (FLAG_debug_code) {
00674
00675
00676
00677 push(holder_reg);
00678
00679 ldr(holder_reg, FieldMemOperand(scratch, HeapObject::kMapOffset));
00680 cmp(holder_reg, Operand(Factory::global_context_map()));
00681 Check(eq, "JSGlobalObject::global_context should be a global context.");
00682 pop(holder_reg);
00683 }
00684
00685
00686 ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
00687 cmp(scratch, Operand(ip));
00688 b(eq, &same_contexts);
00689
00690
00691 if (FLAG_debug_code) {
00692
00693
00694
00695 push(holder_reg);
00696 mov(holder_reg, ip);
00697 cmp(holder_reg, Operand(Factory::null_value()));
00698 Check(ne, "JSGlobalProxy::context() should not be null.");
00699
00700 ldr(holder_reg, FieldMemOperand(holder_reg, HeapObject::kMapOffset));
00701 cmp(holder_reg, Operand(Factory::global_context_map()));
00702 Check(eq, "JSGlobalObject::global_context should be a global context.");
00703
00704 pop(holder_reg);
00705
00706 ldr(ip, FieldMemOperand(holder_reg, JSGlobalProxy::kContextOffset));
00707 }
00708
00709
00710
00711
00712 int token_offset = Context::kHeaderSize +
00713 Context::SECURITY_TOKEN_INDEX * kPointerSize;
00714
00715 ldr(scratch, FieldMemOperand(scratch, token_offset));
00716 ldr(ip, FieldMemOperand(ip, token_offset));
00717 cmp(scratch, Operand(ip));
00718 b(ne, miss);
00719
00720 bind(&same_contexts);
00721 }
00722
00723
00724 void MacroAssembler::CallStub(CodeStub* stub) {
00725 ASSERT(allow_stub_calls());
00726 Call(stub->GetCode(), RelocInfo::CODE_TARGET);
00727 }
00728
00729
00730 void MacroAssembler::StubReturn(int argc) {
00731 ASSERT(argc >= 1 && generating_stub());
00732 if (argc > 1)
00733 add(sp, sp, Operand((argc - 1) * kPointerSize));
00734 Ret();
00735 }
00736
00737
00738 void MacroAssembler::IllegalOperation(int num_arguments) {
00739 if (num_arguments > 0) {
00740 add(sp, sp, Operand(num_arguments * kPointerSize));
00741 }
00742 mov(r0, Operand(Factory::undefined_value()));
00743 }
00744
00745
00746 void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
00747
00748
00749
00750
00751
00752 if (f->nargs >= 0 && f->nargs != num_arguments) {
00753 IllegalOperation(num_arguments);
00754 return;
00755 }
00756
00757 Runtime::FunctionId function_id =
00758 static_cast<Runtime::FunctionId>(f->stub_id);
00759 RuntimeStub stub(function_id, num_arguments);
00760 CallStub(&stub);
00761 }
00762
00763
00764 void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
00765 CallRuntime(Runtime::FunctionForId(fid), num_arguments);
00766 }
00767
00768
00769 void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
00770 int num_arguments) {
00771
00772
00773
00774
00775 mov(r0, Operand(num_arguments));
00776 JumpToBuiltin(ext);
00777 }
00778
00779
00780 void MacroAssembler::JumpToBuiltin(const ExternalReference& builtin) {
00781 #if defined(__thumb__)
00782
00783 ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
00784 #endif
00785 mov(r1, Operand(builtin));
00786 CEntryStub stub;
00787 Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
00788 }
00789
00790
00791 Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id,
00792 bool* resolved) {
00793
00794 int builtins_offset =
00795 JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize);
00796 ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
00797 ldr(r1, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
00798 ldr(r1, FieldMemOperand(r1, builtins_offset));
00799
00800 return Builtins::GetCode(id, resolved);
00801 }
00802
00803
00804 void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
00805 InvokeJSFlags flags) {
00806 bool resolved;
00807 Handle<Code> code = ResolveBuiltin(id, &resolved);
00808
00809 if (flags == CALL_JS) {
00810 Call(code, RelocInfo::CODE_TARGET);
00811 } else {
00812 ASSERT(flags == JUMP_JS);
00813 Jump(code, RelocInfo::CODE_TARGET);
00814 }
00815
00816 if (!resolved) {
00817 const char* name = Builtins::GetName(id);
00818 int argc = Builtins::GetArgumentsCount(id);
00819 uint32_t flags =
00820 Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
00821 Bootstrapper::FixupFlagsIsPCRelative::encode(true);
00822 Unresolved entry = { pc_offset() - sizeof(Instr), flags, name };
00823 unresolved_.Add(entry);
00824 }
00825 }
00826
00827
00828 void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
00829 bool resolved;
00830 Handle<Code> code = ResolveBuiltin(id, &resolved);
00831
00832 mov(target, Operand(code));
00833 if (!resolved) {
00834 const char* name = Builtins::GetName(id);
00835 int argc = Builtins::GetArgumentsCount(id);
00836 uint32_t flags =
00837 Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
00838 Bootstrapper::FixupFlagsIsPCRelative::encode(true);
00839 Unresolved entry = { pc_offset() - sizeof(Instr), flags, name };
00840 unresolved_.Add(entry);
00841 }
00842 }
00843
00844
00845 void MacroAssembler::Assert(Condition cc, const char* msg) {
00846 if (FLAG_debug_code)
00847 Check(cc, msg);
00848 }
00849
00850
00851 void MacroAssembler::Check(Condition cc, const char* msg) {
00852 Label L;
00853 b(cc, &L);
00854 Abort(msg);
00855
00856 bind(&L);
00857 }
00858
00859
00860 void MacroAssembler::Abort(const char* msg) {
00861
00862
00863
00864
00865
00866 intptr_t p1 = reinterpret_cast<intptr_t>(msg);
00867 intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;
00868 ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());
00869 #ifdef DEBUG
00870 if (msg != NULL) {
00871 RecordComment("Abort message: ");
00872 RecordComment(msg);
00873 }
00874 #endif
00875 mov(r0, Operand(p0));
00876 push(r0);
00877 mov(r0, Operand(Smi::FromInt(p1 - p0)));
00878 push(r0);
00879 CallRuntime(Runtime::kAbort, 2);
00880
00881 }
00882
00883 } }