summaryrefslogtreecommitdiffstats
path: root/V8Binding/v8/src/arm/macro-assembler-arm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'V8Binding/v8/src/arm/macro-assembler-arm.cc')
-rw-r--r--V8Binding/v8/src/arm/macro-assembler-arm.cc134
1 files changed, 88 insertions, 46 deletions
diff --git a/V8Binding/v8/src/arm/macro-assembler-arm.cc b/V8Binding/v8/src/arm/macro-assembler-arm.cc
index 4e24063..3d6b8cb 100644
--- a/V8Binding/v8/src/arm/macro-assembler-arm.cc
+++ b/V8Binding/v8/src/arm/macro-assembler-arm.cc
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2009 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -35,11 +35,6 @@
namespace v8 {
namespace internal {
-// Give alias names to registers
-Register cp = { 8 }; // JavaScript context pointer
-Register pp = { 10 }; // parameter pointer
-
-
MacroAssembler::MacroAssembler(void* buffer, int size)
: Assembler(buffer, size),
unresolved_(0),
@@ -51,14 +46,14 @@ MacroAssembler::MacroAssembler(void* buffer, int size)
// We always generate arm code, never thumb code, even if V8 is compiled to
// thumb, so we require inter-working support
-#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+#if defined(__thumb__) && !defined(USE_THUMB_INTERWORK)
#error "flag -mthumb-interwork missing"
#endif
// We do not support thumb inter-working with an arm architecture not supporting
// the blx instruction (below v5t)
-#if defined(__THUMB_INTERWORK__)
+#if defined(USE_THUMB_INTERWORK)
#if !defined(__ARM_ARCH_5T__) && \
!defined(__ARM_ARCH_5TE__) && \
!defined(__ARM_ARCH_7A__) && \
@@ -70,12 +65,12 @@ MacroAssembler::MacroAssembler(void* buffer, int size)
// Using blx may yield better code, so use it when required or when available
-#if defined(__THUMB_INTERWORK__) || defined(__ARM_ARCH_5__)
+#if defined(USE_THUMB_INTERWORK) || defined(__ARM_ARCH_5__)
#define USE_BLX 1
#endif
// Using bx does not yield better code, so use it only when required
-#if defined(__THUMB_INTERWORK__)
+#if defined(USE_THUMB_INTERWORK)
#define USE_BX 1
#endif
@@ -128,26 +123,10 @@ void MacroAssembler::Call(Register target, Condition cond) {
void MacroAssembler::Call(intptr_t target, RelocInfo::Mode rmode,
Condition cond) {
-#if !defined(__arm__)
- if (rmode == RelocInfo::RUNTIME_ENTRY) {
- mov(r2, Operand(target, rmode), LeaveCC, cond);
- // Set lr for return at current pc + 8.
- mov(lr, Operand(pc), LeaveCC, cond);
- // Emit a ldr<cond> pc, [pc + offset of target in constant pool].
- // Notify the simulator of the transition to C code.
- swi(assembler::arm::call_rt_r2);
- } else {
- // set lr for return at current pc + 8
- mov(lr, Operand(pc), LeaveCC, cond);
- // emit a ldr<cond> pc, [pc + offset of target in constant pool]
- mov(pc, Operand(target, rmode), LeaveCC, cond);
- }
-#else
// Set lr for return at current pc + 8.
mov(lr, Operand(pc), LeaveCC, cond);
// Emit a ldr<cond> pc, [pc + offset of target in constant pool].
mov(pc, Operand(target, rmode), LeaveCC, cond);
-#endif // !defined(__arm__)
// If USE_BLX is defined, we could emit a 'mov ip, target', followed by a
// 'blx ip'; however, the code would not be shorter than the above sequence
// and the target address of the call would be referenced by the first
@@ -301,8 +280,8 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
add(r6, sp, Operand(r0, LSL, kPointerSizeLog2));
sub(r6, r6, Operand(kPointerSize));
- // Compute parameter pointer before making changes and save it as ip
- // register so that it is restored as sp register on exit, thereby
+ // Compute callee's stack pointer before making changes and save it as
+ // ip register so that it is restored as sp register on exit, thereby
// popping the args.
// ip = sp + kPointerSize * #args;
@@ -573,41 +552,48 @@ void MacroAssembler::CopyRegistersFromStackToMemory(Register base,
}
#endif
+
void MacroAssembler::PushTryHandler(CodeLocation try_location,
HandlerType type) {
- ASSERT(StackHandlerConstants::kSize == 6 * kPointerSize); // adjust this code
+ // Adjust this code if not the case.
+ ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize);
// 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
+ ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
+ && StackHandlerConstants::kFPOffset == 2 * kPointerSize
+ && StackHandlerConstants::kPCOffset == 3 * kPointerSize);
+ stm(db_w, sp, r3.bit() | fp.bit() | lr.bit());
+ // Save the current handler as the next handler.
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);
+ ASSERT(StackHandlerConstants::kNextOffset == 0);
+ push(r1);
+ // Link this handler as the new current one.
+ str(sp, MemOperand(r3));
} 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());
+ // The frame pointer does not point to a JS frame so we save NULL
+ // for fp. We expect the code throwing an exception to check fp
+ // before dereferencing it to restore the context.
+ mov(ip, Operand(0)); // To save a NULL frame pointer.
mov(r6, Operand(StackHandler::ENTRY));
- push(r6); // state
+ ASSERT(StackHandlerConstants::kStateOffset == 1 * kPointerSize
+ && StackHandlerConstants::kFPOffset == 2 * kPointerSize
+ && StackHandlerConstants::kPCOffset == 3 * kPointerSize);
+ stm(db_w, sp, r6.bit() | ip.bit() | lr.bit());
+ // Save the current handler as the next handler.
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
+ ASSERT(StackHandlerConstants::kNextOffset == 0);
+ push(r6);
+ // Link this handler as the new current one.
+ str(sp, MemOperand(r7));
}
}
@@ -759,6 +745,62 @@ void MacroAssembler::CheckAccessGlobalProxy(Register holder_reg,
}
+void MacroAssembler::CompareObjectType(Register function,
+ Register map,
+ Register type_reg,
+ InstanceType type) {
+ ldr(map, FieldMemOperand(function, HeapObject::kMapOffset));
+ ldrb(type_reg, FieldMemOperand(map, Map::kInstanceTypeOffset));
+ cmp(type_reg, Operand(type));
+}
+
+
+void MacroAssembler::TryGetFunctionPrototype(Register function,
+ Register result,
+ Register scratch,
+ Label* miss) {
+ // Check that the receiver isn't a smi.
+ BranchOnSmi(function, miss);
+
+ // Check that the function really is a function. Load map into result reg.
+ CompareObjectType(function, result, scratch, JS_FUNCTION_TYPE);
+ b(ne, miss);
+
+ // Make sure that the function has an instance prototype.
+ Label non_instance;
+ ldrb(scratch, FieldMemOperand(result, Map::kBitFieldOffset));
+ tst(scratch, Operand(1 << Map::kHasNonInstancePrototype));
+ b(ne, &non_instance);
+
+ // Get the prototype or initial map from the function.
+ ldr(result,
+ FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
+
+ // If the prototype or initial map is the hole, don't return it and
+ // simply miss the cache instead. This will allow us to allocate a
+ // prototype object on-demand in the runtime system.
+ cmp(result, Operand(Factory::the_hole_value()));
+ b(eq, miss);
+
+ // If the function does not have an initial map, we're done.
+ Label done;
+ CompareObjectType(result, scratch, scratch, MAP_TYPE);
+ b(ne, &done);
+
+ // Get the prototype from the initial map.
+ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
+ jmp(&done);
+
+ // Non-instance prototype: Fetch prototype from constructor field
+ // in initial map.
+ bind(&non_instance);
+ ldr(result, FieldMemOperand(result, Map::kConstructorOffset));
+
+ // All done.
+ bind(&done);
+}
+
+
void MacroAssembler::CallStub(CodeStub* stub) {
ASSERT(allow_stub_calls()); // stub calls are not allowed in some stubs
Call(stub->GetCode(), RelocInfo::CODE_TARGET);