⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macro-assembler-arm.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
}void MacroAssembler::InvokeCode(Register code,                                const ParameterCount& expected,                                const ParameterCount& actual,                                InvokeFlag flag) {  Label done;  InvokePrologue(expected, actual, Handle<Code>::null(), code, &done, flag);  if (flag == CALL_FUNCTION) {    Call(code);  } else {    ASSERT(flag == JUMP_FUNCTION);    Jump(code);  }  // Continue here if InvokePrologue does handle the invocation due to  // mismatched parameter counts.  bind(&done);}void MacroAssembler::InvokeCode(Handle<Code> code,                                const ParameterCount& expected,                                const ParameterCount& actual,                                RelocInfo::Mode rmode,                                InvokeFlag flag) {  Label done;  InvokePrologue(expected, actual, code, no_reg, &done, flag);  if (flag == CALL_FUNCTION) {    Call(code, rmode);  } else {    Jump(code, rmode);  }  // Continue here if InvokePrologue does handle the invocation due to  // mismatched parameter counts.  bind(&done);}void MacroAssembler::InvokeFunction(Register fun,                                    const ParameterCount& actual,                                    InvokeFlag flag) {  // Contract with called JS functions requires that function is passed in r1.  ASSERT(fun.is(r1));  Register expected_reg = r2;  Register code_reg = r3;  ldr(code_reg, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));  ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));  ldr(expected_reg,      FieldMemOperand(code_reg,                      SharedFunctionInfo::kFormalParameterCountOffset));  ldr(code_reg,      MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));  add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));  ParameterCount expected(expected_reg);  InvokeCode(code_reg, expected, actual, flag);}void MacroAssembler::SaveRegistersToMemory(RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Copy the content of registers to memory location.  for (int i = 0; i < kNumJSCallerSaved; i++) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      Register reg = { r };      mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));      str(reg, MemOperand(ip));    }  }}void MacroAssembler::RestoreRegistersFromMemory(RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Copy the content of memory location to registers.  for (int i = kNumJSCallerSaved; --i >= 0;) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      Register reg = { r };      mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));      ldr(reg, MemOperand(ip));    }  }}void MacroAssembler::CopyRegistersFromMemoryToStack(Register base,                                                    RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Copy the content of the memory location to the stack and adjust base.  for (int i = kNumJSCallerSaved; --i >= 0;) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));      ldr(ip, MemOperand(ip));      str(ip, MemOperand(base, 4, NegPreIndex));    }  }}void MacroAssembler::CopyRegistersFromStackToMemory(Register base,                                                    Register scratch,                                                    RegList regs) {  ASSERT((regs & ~kJSCallerSaved) == 0);  // Copy the content of the stack to the memory location and adjust base.  for (int i = 0; i < kNumJSCallerSaved; i++) {    int r = JSCallerSavedCode(i);    if ((regs & (1 << r)) != 0) {      mov(ip, Operand(ExternalReference(Debug_Address::Register(i))));      ldr(scratch, MemOperand(base, 4, PostIndex));      str(scratch, MemOperand(ip));    }  }}void MacroAssembler::PushTryHandler(CodeLocation try_location,                                    HandlerType type) {  ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize);  // adjust this code  // The pc (return address) is passed in register lr.  if (try_location == IN_JAVASCRIPT) {    stm(db_w, sp, pp.bit() | fp.bit() | lr.bit());    if (type == TRY_CATCH_HANDLER) {      mov(r3, Operand(StackHandler::TRY_CATCH));    } else {      mov(r3, Operand(StackHandler::TRY_FINALLY));    }    push(r3);  // state    mov(r3, Operand(ExternalReference(Top::k_handler_address)));    ldr(r1, MemOperand(r3));    push(r1);  // next sp    str(sp, MemOperand(r3));  // chain handler    mov(r0, Operand(Smi::FromInt(StackHandler::kCodeNotPresent)));  // new TOS    push(r0);  } else {    // Must preserve r0-r4, r5-r7 are available.    ASSERT(try_location == IN_JS_ENTRY);    // The parameter pointer is meaningless here and fp does not point to a JS    // frame. So we save NULL for both pp and fp. We expect the code throwing an    // exception to check fp before dereferencing it to restore the context.    mov(pp, Operand(0));  // set pp to NULL    mov(ip, Operand(0));  // to save a NULL fp    stm(db_w, sp, pp.bit() | ip.bit() | lr.bit());    mov(r6, Operand(StackHandler::ENTRY));    push(r6);  // state    mov(r7, Operand(ExternalReference(Top::k_handler_address)));    ldr(r6, MemOperand(r7));    push(r6);  // next sp    str(sp, MemOperand(r7));  // chain handler    mov(r5, Operand(Smi::FromInt(StackHandler::kCodeNotPresent)));  // new TOS    push(r5);  // flush TOS  }}Register MacroAssembler::CheckMaps(JSObject* object, Register object_reg,                                   JSObject* holder, Register holder_reg,                                   Register scratch,                                   Label* miss) {  // Make sure there's no overlap between scratch and the other  // registers.  ASSERT(!scratch.is(object_reg) && !scratch.is(holder_reg));  // Keep track of the current object in register reg.  Register reg = object_reg;  int depth = 1;  // Check the maps in the prototype chain.  // Traverse the prototype chain from the object and do map checks.  while (object != holder) {    depth++;    // Only global objects and objects that do not require access    // checks are allowed in stubs.    ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());    // Get the map of the current object.    ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));    cmp(scratch, Operand(Handle<Map>(object->map())));    // Branch on the result of the map check.    b(ne, miss);    // Check access rights to the global object.  This has to happen    // after the map check so that we know that the object is    // actually a global object.    if (object->IsJSGlobalObject()) {      CheckAccessGlobal(reg, scratch, miss);      // Restore scratch register to be the map of the object.  In the      // new space case below, we load the prototype from the map in      // the scratch register.      ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));    }    reg = holder_reg;  // from now the object is in holder_reg    JSObject* prototype = JSObject::cast(object->GetPrototype());    if (Heap::InNewSpace(prototype)) {      // The prototype is in new space; we cannot store a reference      // to it in the code. Load it from the map.      ldr(reg, FieldMemOperand(scratch, Map::kPrototypeOffset));    } else {      // The prototype is in old space; load it directly.      mov(reg, Operand(Handle<JSObject>(prototype)));    }    // Go to the next object in the prototype chain.    object = prototype;  }  // Check the holder map.  ldr(scratch, FieldMemOperand(reg, HeapObject::kMapOffset));  cmp(scratch, Operand(Handle<Map>(object->map())));  b(ne, miss);  // Log the check depth.  LOG(IntEvent("check-maps-depth", depth));  // Perform security check for access to the global object and return  // the holder register.  ASSERT(object == holder);  ASSERT(object->IsJSGlobalObject() || !object->IsAccessCheckNeeded());  if (object->IsJSGlobalObject()) {    CheckAccessGlobal(reg, scratch, miss);  }  return reg;}void MacroAssembler::CheckAccessGlobal(Register holder_reg,                                       Register scratch,                                       Label* miss) {  ASSERT(!holder_reg.is(scratch));  // Load the security context.  mov(scratch, Operand(Top::security_context_address()));  ldr(scratch, MemOperand(scratch));  // In debug mode, make sure the security context is set.  if (kDebug) {    cmp(scratch, Operand(0));    Check(ne, "we should not have an empty security context");  }  // Load the global object of the security context.  int offset = Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;  ldr(scratch, FieldMemOperand(scratch, offset));  // Check that the security token in the calling global object is  // compatible with the security token in the receiving global  // object.  ldr(scratch, FieldMemOperand(scratch, JSGlobalObject::kSecurityTokenOffset));  ldr(ip, FieldMemOperand(holder_reg, JSGlobalObject::kSecurityTokenOffset));  cmp(scratch, Operand(ip));  b(ne, miss);}void MacroAssembler::CallStub(CodeStub* stub) {  ASSERT(allow_stub_calls());  // stub calls are not allowed in some stubs  Call(stub->GetCode(), RelocInfo::CODE_TARGET);}void MacroAssembler::StubReturn(int argc) {  ASSERT(argc >= 1 && generating_stub());  if (argc > 1)    add(sp, sp, Operand((argc - 1) * kPointerSize));  Ret();}void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {  // All parameters are on the stack.  r0 has the return value after call.  // Either the expected number of arguments is unknown, or the actual  // number of arguments match the expectation.  ASSERT(f->nargs < 0 || f->nargs == num_arguments);  Runtime::FunctionId function_id =      static_cast<Runtime::FunctionId>(f->stub_id);  RuntimeStub stub(function_id, num_arguments);  CallStub(&stub);}void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {  CallRuntime(Runtime::FunctionForId(fid), num_arguments);}void MacroAssembler::TailCallRuntime(const ExternalReference& ext,                                     int num_arguments) {  // TODO(1236192): Most runtime routines don't need the number of  // arguments passed in because it is constant. At some point we  // should remove this need and make the runtime routine entry code  // smarter.  mov(r0, Operand(num_arguments));  JumpToBuiltin(ext);}void MacroAssembler::JumpToBuiltin(const ExternalReference& builtin) {#if defined(__thumb__)  // Thumb mode builtin.  ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);#endif  mov(r1, Operand(builtin));  CEntryStub stub;  Jump(stub.GetCode(), RelocInfo::CODE_TARGET);}Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id,                                            bool* resolved) {  // Contract with compiled functions is that the function is passed in r1.  int builtins_offset =      JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize);  ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));  ldr(r1, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));  ldr(r1, FieldMemOperand(r1, builtins_offset));  return Builtins::GetCode(id, resolved);}void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,                                   InvokeJSFlags flags) {  bool resolved;  Handle<Code> code = ResolveBuiltin(id, &resolved);  if (flags == CALL_JS) {    Call(code, RelocInfo::CODE_TARGET);  } else {    ASSERT(flags == JUMP_JS);    Jump(code, RelocInfo::CODE_TARGET);  }  if (!resolved) {    const char* name = Builtins::GetName(id);    int argc = Builtins::GetArgumentsCount(id);    uint32_t flags =        Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |        Bootstrapper::FixupFlagsIsPCRelative::encode(true);    Unresolved entry = { pc_offset() - sizeof(Instr), flags, name };    unresolved_.Add(entry);  }}void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {  bool resolved;  Handle<Code> code = ResolveBuiltin(id, &resolved);  mov(target, Operand(code));  if (!resolved) {    const char* name = Builtins::GetName(id);    int argc = Builtins::GetArgumentsCount(id);    uint32_t flags =        Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |        Bootstrapper::FixupFlagsIsPCRelative::encode(true);    Unresolved entry = { pc_offset() - sizeof(Instr), flags, name };    unresolved_.Add(entry);  }}void MacroAssembler::Assert(Condition cc, const char* msg) {  if (FLAG_debug_code)    Check(cc, msg);}void MacroAssembler::Check(Condition cc, const char* msg) {  Label L;  b(cc, &L);  Abort(msg);  // will not return here  bind(&L);}void MacroAssembler::Abort(const char* msg) {  // We want to pass the msg string like a smi to avoid GC  // problems, however msg is not guaranteed to be aligned  // properly. Instead, we pass an aligned pointer that is  // a proper v8 smi, but also pass the aligment difference  // from the real pointer as a smi.  intptr_t p1 = reinterpret_cast<intptr_t>(msg);  intptr_t p0 = (p1 & ~kSmiTagMask) + kSmiTag;  ASSERT(reinterpret_cast<Object*>(p0)->IsSmi());#ifdef DEBUG  if (msg != NULL) {    RecordComment("Abort message: ");    RecordComment(msg);  }#endif  mov(r0, Operand(p0));  push(r0);  mov(r0, Operand(Smi::FromInt(p1 - p0)));  push(r0);  CallRuntime(Runtime::kAbort, 2);  // will not return here}} }  // namespace v8::internal

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -