Author: [EMAIL PROTECTED]
Date: Fri Nov 14 04:47:25 2008
New Revision: 756
Modified:
branches/experimental/toiger/SConstruct
branches/experimental/toiger/include/v8.h
branches/experimental/toiger/src/api.cc
branches/experimental/toiger/src/codegen-arm.cc
branches/experimental/toiger/src/codegen-ia32.cc
branches/experimental/toiger/src/ic-arm.cc
branches/experimental/toiger/src/simulator-arm.cc
branches/experimental/toiger/src/simulator-arm.h
branches/experimental/toiger/src/stub-cache-arm.cc
branches/experimental/toiger/src/top.cc
branches/experimental/toiger/test/cctest/cctest.status
branches/experimental/toiger/tools/visual_studio/arm.vsprops
Log:
Experimental: periodic merge to the experimental branch from
bleeding_edge. Merge bleeding [EMAIL PROTECTED]
Review URL: http://codereview.chromium.org/10945
Modified: branches/experimental/toiger/SConstruct
==============================================================================
--- branches/experimental/toiger/SConstruct (original)
+++ branches/experimental/toiger/SConstruct Fri Nov 14 04:47:25 2008
@@ -106,7 +106,10 @@
'CPPDEFINES': ['BUILDING_V8_SHARED']
},
'arch:arm': {
- 'CPPDEFINES': ['ARM']
+ 'CPPDEFINES': ['ARM'],
+ # /wd4996 is to silence the warning about sscanf
+ # used by the arm simulator.
+ 'WARNINGFLAGS': ['/wd4996']
},
'disassembler:on': {
'CPPDEFINES': ['ENABLE_DISASSEMBLER']
Modified: branches/experimental/toiger/include/v8.h
==============================================================================
--- branches/experimental/toiger/include/v8.h (original)
+++ branches/experimental/toiger/include/v8.h Fri Nov 14 04:47:25 2008
@@ -2052,6 +2052,7 @@
void* message_;
bool is_verbose_;
bool capture_message_;
+ void* js_handler_;
};
Modified: branches/experimental/toiger/src/api.cc
==============================================================================
--- branches/experimental/toiger/src/api.cc (original)
+++ branches/experimental/toiger/src/api.cc Fri Nov 14 04:47:25 2008
@@ -1081,7 +1081,8 @@
exception_(i::Heap::the_hole_value()),
message_(i::Smi::FromInt(0)),
is_verbose_(false),
- capture_message_(true) {
+ capture_message_(true),
+ js_handler_(NULL) {
i::Top::RegisterTryCatchHandler(this);
}
Modified: branches/experimental/toiger/src/codegen-arm.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-arm.cc (original)
+++ branches/experimental/toiger/src/codegen-arm.cc Fri Nov 14 04:47:25 2008
@@ -3128,56 +3128,47 @@
Expression* right = node->right();
Token::Value op = node->op();
- // NOTE: To make null checks efficient, we check if either left or
- // right is the literal 'null'. If so, we optimize the code by
- // inlining a null check instead of calling the (very) general
- // runtime routine for checking equality.
-
+ // To make null checks efficient, we check if either left or right is the
+ // literal 'null'. If so, we optimize the code by inlining a null check
+ // instead of calling the (very) general runtime routine for checking
+ // equality.
if (op == Token::EQ || op == Token::EQ_STRICT) {
bool left_is_null =
- left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
+ left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
bool right_is_null =
- right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
- // The 'null' value is only equal to 'null' or 'undefined'.
+ right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
+ // The 'null' value can only be equal to 'null' or 'undefined'.
if (left_is_null || right_is_null) {
Load(left_is_null ? right : left);
- JumpTarget exit(this);
- JumpTarget undetectable(this);
frame_->Pop(r0);
__ cmp(r0, Operand(Factory::null_value()));
- // The 'null' value is only equal to 'undefined' if using
- // non-strict comparisons.
+ // The 'null' value is only equal to 'undefined' if using non-strict
+ // comparisons.
if (op != Token::EQ_STRICT) {
- exit.Branch(eq);
+ true_target()->Branch(eq);
+
__ cmp(r0, Operand(Factory::undefined_value()));
+ true_target()->Branch(eq);
- // NOTE: it can be undetectable object.
- exit.Branch(eq);
__ tst(r0, Operand(kSmiTagMask));
+ false_target()->Branch(eq);
- undetectable.Branch(ne);
- false_target()->Jump();
-
- undetectable.Bind();
- __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
- __ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
- __ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
- __ cmp(r2, Operand(1 << Map::kIsUndetectable));
+ // It can be an undetectable object.
+ __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
+ __ ldrb(r0, FieldMemOperand(r0, Map::kBitFieldOffset));
+ __ and_(r0, r0, Operand(1 << Map::kIsUndetectable));
+ __ cmp(r0, Operand(1 << Map::kIsUndetectable));
}
- exit.Bind();
-
cc_reg_ = eq;
return;
}
}
-
- // NOTE: To make typeof testing for natives implemented in
- // JavaScript really efficient, we generate special code for
- // expressions of the form: 'typeof <expression> == <string>'.
-
+ // To make typeof testing for natives implemented in JavaScript really
+ // efficient, we generate special code for expressions of the form:
+ // 'typeof <expression> == <string>'.
UnaryOperation* operation = left->AsUnaryOperation();
if ((op == Token::EQ || op == Token::EQ_STRICT) &&
(operation != NULL && operation->op() == Token::TYPEOF) &&
@@ -3202,7 +3193,7 @@
__ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
- // NOTE: it might be an undetectable string object
+ // It can be an undetectable string object.
__ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
__ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
__ cmp(r2, Operand(1 << Map::kIsUndetectable));
@@ -3225,7 +3216,7 @@
__ tst(r1, Operand(kSmiTagMask));
false_target()->Branch(eq);
- // NOTE: it can be undetectable object.
+ // It can be an undetectable object.
__ ldr(r1, FieldMemOperand(r1, HeapObject::kMapOffset));
__ ldrb(r2, FieldMemOperand(r1, Map::kBitFieldOffset));
__ and_(r2, r2, Operand(1 << Map::kIsUndetectable));
@@ -3249,7 +3240,7 @@
__ cmp(r1, Operand(Factory::null_value()));
true_target()->Branch(eq);
- // NOTE: it might be an undetectable object.
+ // It can be an undetectable object.
__ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
__ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
__ cmp(r1, Operand(1 << Map::kIsUndetectable));
@@ -3262,8 +3253,8 @@
cc_reg_ = le;
} else {
- // Uncommon case: Typeof testing against a string literal that
- // is never returned from the typeof operator.
+ // Uncommon case: typeof testing against a string literal that is
+ // never returned from the typeof operator.
false_target()->Jump();
}
return;
@@ -3391,9 +3382,15 @@
// distinction between expressions in a typeof and not in a typeof.
Comment cmnt(masm, "[ Load from keyed Property");
ASSERT(property != NULL);
- // TODO(1224671): Implement inline caching for keyed loads as on
ia32.
- GetPropertyStub stub;
- frame->CallStub(&stub, 0);
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
+
+ Variable* var = expression_->AsVariableProxy()->AsVariable();
+ if (var != NULL) {
+ ASSERT(var->is_global());
+ frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
+ } else {
+ frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
+ }
frame->Push(r0);
break;
}
@@ -3500,11 +3497,11 @@
case NAMED: {
Comment cmnt(masm, "[ Store to named Property");
// Call the appropriate IC code.
+ Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
frame->Pop(r0); // value
// Setup the name register.
Handle<String> name(GetName());
__ mov(r2, Operand(name));
- Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Initialize));
frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
frame->Push(r0);
break;
@@ -3515,9 +3512,12 @@
Property* property = expression_->AsProperty();
ASSERT(property != NULL);
__ RecordPosition(property->position());
+
+ // Call IC code.
+ Handle<Code>
ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
+ // TODO(1222589): Make the IC grab the values from the stack.
frame->Pop(r0); // value
- SetPropertyStub stub;
- frame->CallStub(&stub, 0);
+ frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
frame->Push(r0);
break;
}
Modified: branches/experimental/toiger/src/codegen-ia32.cc
==============================================================================
--- branches/experimental/toiger/src/codegen-ia32.cc (original)
+++ branches/experimental/toiger/src/codegen-ia32.cc Fri Nov 14 04:47:25
2008
@@ -3692,55 +3692,47 @@
Expression* right = node->right();
Token::Value op = node->op();
- // NOTE: To make null checks efficient, we check if either left or
- // right is the literal 'null'. If so, we optimize the code by
- // inlining a null check instead of calling the (very) general
- // runtime routine for checking equality.
-
+ // To make null checks efficient, we check if either left or right is the
+ // literal 'null'. If so, we optimize the code by inlining a null check
+ // instead of calling the (very) general runtime routine for checking
+ // equality.
if (op == Token::EQ || op == Token::EQ_STRICT) {
bool left_is_null =
- left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
+ left->AsLiteral() != NULL && left->AsLiteral()->IsNull();
bool right_is_null =
- right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
- // The 'null' value is only equal to 'null' or 'undefined'.
+ right->AsLiteral() != NULL && right->AsLiteral()->IsNull();
+ // The 'null' value can only be equal to 'null' or 'undefined'.
if (left_is_null || right_is_null) {
Load(left_is_null ? right : left);
- JumpTarget exit(this);
- JumpTarget undetectable(this);
frame_->Pop(eax);
__ cmp(eax, Factory::null_value());
- // The 'null' value is only equal to 'undefined' if using
- // non-strict comparisons.
+ // The 'null' value is only equal to 'undefined' if using non-strict
+ // comparisons.
if (op != Token::EQ_STRICT) {
- exit.Branch(equal);
+ true_target()->Branch(equal);
+
__ cmp(eax, Factory::undefined_value());
+ true_target()->Branch(equal);
- // NOTE: it can be an undetectable object.
- exit.Branch(equal);
__ test(eax, Immediate(kSmiTagMask));
+ false_target()->Branch(equal);
- undetectable.Branch(not_equal);
- false_target()->Jump();
-
- undetectable.Bind();
- __ mov(edx, FieldOperand(eax, HeapObject::kMapOffset));
- __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
- __ and_(ecx, 1 << Map::kIsUndetectable);
- __ cmp(ecx, 1 << Map::kIsUndetectable);
+ // It can be an undetectable object.
+ __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset));
+ __ movzx_b(eax, FieldOperand(eax, Map::kBitFieldOffset));
+ __ and_(eax, 1 << Map::kIsUndetectable);
+ __ cmp(eax, 1 << Map::kIsUndetectable);
}
- exit.Bind();
-
cc_reg_ = equal;
return;
}
}
- // NOTE: To make typeof testing for natives implemented in
- // JavaScript really efficient, we generate special code for
- // expressions of the form: 'typeof <expression> == <string>'.
-
+ // To make typeof testing for natives implemented in JavaScript really
+ // efficient, we generate special code for expressions of the form:
+ // 'typeof <expression> == <string>'.
UnaryOperation* operation = left->AsUnaryOperation();
if ((op == Token::EQ || op == Token::EQ_STRICT) &&
(operation != NULL && operation->op() == Token::TYPEOF) &&
@@ -3748,7 +3740,7 @@
right->AsLiteral()->handle()->IsString())) {
Handle<String> check(String::cast(*right->AsLiteral()->handle()));
- // Load the operand, move it to register edx, and restore TOS.
+ // Load the operand and move it to register edx.
LoadTypeofExpression(operation->expression());
frame_->Pop(edx);
@@ -3765,7 +3757,7 @@
__ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
- // NOTE: it might be an undetectable string object
+ // It can be an undetectable string object.
__ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
__ and_(ecx, 1 << Map::kIsUndetectable);
__ cmp(ecx, 1 << Map::kIsUndetectable);
@@ -3788,7 +3780,7 @@
__ test(edx, Immediate(kSmiTagMask));
false_target()->Branch(zero);
- // NOTE: it can be an undetectable object.
+ // It can be an undetectable object.
__ mov(edx, FieldOperand(edx, HeapObject::kMapOffset));
__ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
__ and_(ecx, 1 << Map::kIsUndetectable);
@@ -3812,7 +3804,7 @@
__ cmp(edx, Factory::null_value());
true_target()->Branch(equal);
- // NOTE: it might be an undetectable object
+ // It can be an undetectable object.
__ movzx_b(edx, FieldOperand(ecx, Map::kBitFieldOffset));
__ and_(edx, 1 << Map::kIsUndetectable);
__ cmp(edx, 1 << Map::kIsUndetectable);
@@ -3825,8 +3817,8 @@
cc_reg_ = less_equal;
} else {
- // Uncommon case: Typeof testing against a string literal that
- // is never returned from the typeof operator.
+ // Uncommon case: typeof testing against a string literal that is
+ // never returned from the typeof operator.
false_target()->Jump();
// TODO(): Can this cause a problem because it is an expression that
// exits without a virtual frame in place?
Modified: branches/experimental/toiger/src/ic-arm.cc
==============================================================================
--- branches/experimental/toiger/src/ic-arm.cc (original)
+++ branches/experimental/toiger/src/ic-arm.cc Fri Nov 14 04:47:25 2008
@@ -136,24 +136,9 @@
__ ldr(r0, MemOperand(sp, 0));
- // Check that the receiver isn't a smi.
- __ tst(r0, Operand(kSmiTagMask));
- __ b(eq, &miss);
-
- // Check that the object is a JS array.
- __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
- __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
- __ cmp(r1, Operand(JS_ARRAY_TYPE));
- __ b(ne, &miss);
-
- // Load length directly from the JS array.
- __ ldr(r0, FieldMemOperand(r0, JSArray::kLengthOffset));
- __ Ret();
-
- // Cache miss: Jump to runtime.
+ StubCompiler::GenerateLoadArrayLength(masm, r0, r3, &miss);
__ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
@@ -185,7 +170,6 @@
// -- lr : return address
// -- [sp] : receiver
// -----------------------------------
-
Label miss, load_length, check_wrapper;
__ ldr(r0, MemOperand(sp, 0));
@@ -216,8 +200,7 @@
// Cache miss: Jump to runtime.
__ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
}
@@ -509,33 +492,87 @@
// -- [sp] : receiver
// -----------------------------------
- __ ldr(r0, MemOperand(sp, 0));
- __ push(r0);
- __ push(r2);
+ __ ldr(r3, MemOperand(sp, 0));
+ __ stm(db_w, sp, r2.bit() | r3.bit());
// Perform tail call to the entry.
__ TailCallRuntime(f, 2);
}
-// TODO(1224671): ICs for keyed load/store is not implemented on ARM.
+// TODO(1224671): ICs for keyed load/store is not completed on ARM.
+Object* KeyedLoadIC_Miss(Arguments args);
+
+
void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
+ Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
}
+
void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference&
f) {
+ // ---------- S t a t e --------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+ __ ldm(ia, sp, r2.bit() | r3.bit());
+ __ stm(db_w, sp, r2.bit() | r3.bit());
+
+ __ TailCallRuntime(f, 2);
}
+
+// TODO(1224671): implement the fast case.
void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
+ // ---------- S t a t e --------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+
+ KeyedLoadIC::Generate(masm,
ExternalReference(Runtime::kKeyedGetProperty));
}
+
void KeyedStoreIC::Generate(MacroAssembler* masm,
const ExternalReference& f) {
+ // ---------- S t a t e --------------
+ // -- r0 : value
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[1] : receiver
+
+ __ ldm(ia, sp, r2.bit() | r3.bit());
+ __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+ __ TailCallRuntime(f, 3);
}
+
+// TODO(1224671): implement the fast case.
void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
+ // ---------- S t a t e --------------
+ // -- r0 : value
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[1] : receiver
+
+ KeyedStoreIC::Generate(masm, ExternalReference(Runtime::kSetProperty));
}
+
void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
+ // ---------- S t a t e --------------
+ // -- r0 : value
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[1] : receiver
+ // ----------- S t a t e -------------
+
+ __ ldm(ia, sp, r2.bit() | r3.bit());
+ __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
+
+ // Perform tail call to the entry.
+ __ TailCallRuntime(
+ ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3);
}
Modified: branches/experimental/toiger/src/simulator-arm.cc
==============================================================================
--- branches/experimental/toiger/src/simulator-arm.cc (original)
+++ branches/experimental/toiger/src/simulator-arm.cc Fri Nov 14 04:47:25
2008
@@ -48,11 +48,7 @@
// SScanF not beeing implemented in a platform independent was through
// ::v8::internal::OS in the same way as SNPrintF is that the Windows C
Run-Time
// Library does not provide vsscanf.
-#ifdef WIN32
-#define SScanF sscanf_s
-#else
#define SScanF sscanf // NOLINT
-#endif
// The Debugger class is used by the simulator while debugging simulated
ARM
// code.
@@ -382,19 +378,20 @@
}
-// This is the Simulator singleton. Currently only one thread is supported
by
-// V8. If we had multiple threads, then we should have a Simulator
instance on
-// a per thread basis.
-static Simulator* the_sim = NULL;
+// Create one simulator per thread and keep it in thread local storage.
+static v8::internal::Thread::LocalStorageKey simulator_key =
+ v8::internal::Thread::CreateThreadLocalKey();
-
-// Get the active Simulator for the current thread. See comment above about
-// using a singleton currently.
+// Get the active Simulator for the current thread.
Simulator* Simulator::current() {
- if (the_sim == NULL) {
- the_sim = new Simulator();
+ Simulator* sim = reinterpret_cast<Simulator*>(
+ v8::internal::Thread::GetThreadLocal(simulator_key));
+ if (sim == NULL) {
+ // TODO(146): delete the simulator object when a thread goes away.
+ sim = new Simulator();
+ v8::internal::Thread::SetThreadLocal(simulator_key, sim);
}
- return the_sim;
+ return sim;
}
@@ -1495,7 +1492,7 @@
//
-void Simulator::execute() {
+void Simulator::Execute() {
// Get the PC to simulate. Cannot use the accessor here as we need the
// raw PC value and not the one used as input to arithmetic instructions.
int program_counter = get_pc();
@@ -1527,8 +1524,8 @@
}
-Object* Simulator::call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
- int32_t p3, int32_t p4) {
+Object* Simulator::Call(int32_t entry, int32_t p0, int32_t p1, int32_t p2,
+ int32_t p3, int32_t p4) {
// Setup parameters
set_register(r0, p0);
set_register(r1, p1);
@@ -1570,7 +1567,7 @@
set_register(r11, callee_saved_value);
// Start the simulation
- execute();
+ Execute();
// Check that the callee-saved registers have been preserved.
CHECK_EQ(get_register(r4), callee_saved_value);
Modified: branches/experimental/toiger/src/simulator-arm.h
==============================================================================
--- branches/experimental/toiger/src/simulator-arm.h (original)
+++ branches/experimental/toiger/src/simulator-arm.h Fri Nov 14 04:47:25
2008
@@ -54,7 +54,7 @@
// When running with the simulator transition into simulated execution at
this
// point.
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4) \
- assembler::arm::Simulator::current()->call((int32_t)entry, (int32_t)p0, \
+ assembler::arm::Simulator::current()->Call((int32_t)entry, (int32_t)p0, \
(int32_t)p1, (int32_t)p2, (int32_t)p3, (int32_t)p4)
// The simulator has its own stack. Thus it has a different stack limit
from
@@ -103,12 +103,12 @@
uintptr_t StackLimit() const;
// Executes ARM instructions until the PC reaches end_sim_pc.
- void execute();
+ void Execute();
// V8 generally calls into generated code with 5 parameters. This is a
// convenience funtion, which sets up the simulator state and grabs the
// result on return.
- v8::internal::Object* call(int32_t entry, int32_t p0, int32_t p1,
+ v8::internal::Object* Call(int32_t entry, int32_t p0, int32_t p1,
int32_t p2, int32_t p3, int32_t p4);
private:
Modified: branches/experimental/toiger/src/stub-cache-arm.cc
==============================================================================
--- branches/experimental/toiger/src/stub-cache-arm.cc (original)
+++ branches/experimental/toiger/src/stub-cache-arm.cc Fri Nov 14 04:47:25
2008
@@ -169,6 +169,141 @@
}
+void StubCompiler::GenerateLoadField(MacroAssembler* masm,
+ JSObject* object,
+ JSObject* holder,
+ Register receiver,
+ Register scratch1,
+ Register scratch2,
+ int index,
+ Label* miss_label) {
+ // Check that the receiver isn't a smi.
+ __ tst(receiver, Operand(kSmiTagMask));
+ __ b(eq, miss_label);
+
+ // Check that the maps haven't changed.
+ Register reg =
+ __ CheckMaps(object, receiver, holder, scratch1, scratch2,
miss_label);
+ GenerateFastPropertyLoad(masm, r0, reg, holder, index);
+ __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadConstant(MacroAssembler* masm,
+ JSObject* object,
+ JSObject* holder,
+ Register receiver,
+ Register scratch1,
+ Register scratch2,
+ Object* value,
+ Label* miss_label) {
+ // Check that the receiver isn't a smi.
+ __ tst(receiver, Operand(kSmiTagMask));
+ __ b(eq, miss_label);
+
+ // Check that the maps haven't changed.
+ Register reg =
+ __ CheckMaps(object, receiver, holder, scratch1, scratch2,
miss_label);
+
+ // Return the constant value.
+ __ mov(r0, Operand(Handle<Object>(value)));
+ __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadCallback(MacroAssembler* masm,
+ JSObject* object,
+ JSObject* holder,
+ Register receiver,
+ Register name,
+ Register scratch1,
+ Register scratch2,
+ AccessorInfo* callback,
+ Label* miss_label) {
+ // Check that the receiver isn't a smi.
+ __ tst(receiver, Operand(kSmiTagMask));
+ __ b(eq, miss_label);
+
+ // Check that the maps haven't changed.
+ Register reg =
+ __ CheckMaps(object, receiver, holder, scratch1, scratch2,
miss_label);
+
+ // Push the arguments on the JS stack of the caller.
+ __ push(receiver); // receiver
+ __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
+ __ push(ip);
+ __ push(name); // name
+ __ push(reg); // holder
+
+ // Do tail-call to the runtime system.
+ ExternalReference load_callback_property =
+ ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
+ __ TailCallRuntime(load_callback_property, 4);
+}
+
+
+void StubCompiler::GenerateLoadInterceptor(MacroAssembler* masm,
+ JSObject* object,
+ JSObject* holder,
+ Register receiver,
+ Register name,
+ Register scratch1,
+ Register scratch2,
+ Label* miss_label) {
+ // Check that the receiver isn't a smi.
+ __ tst(receiver, Operand(kSmiTagMask));
+ __ b(eq, miss_label);
+
+ // Check that the maps haven't changed.
+ Register reg =
+ __ CheckMaps(object, receiver, holder, scratch1, scratch2,
miss_label);
+
+ // Push the arguments on the JS stack of the caller.
+ __ push(receiver); // receiver
+ __ push(reg); // holder
+ __ push(name); // name
+
+ // Do tail-call to the runtime system.
+ ExternalReference load_ic_property =
+ ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
+ __ TailCallRuntime(load_ic_property, 3);
+}
+
+
+void StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm,
+ Register receiver,
+ Register scratch,
+ Label* miss_label) {
+ // Check that the receiver isn't a smi.
+ __ tst(receiver, Operand(kSmiTagMask));
+ __ b(eq, miss_label);
+
+ // Check that the object is a JS array.
+ __ ldr(scratch, FieldMemOperand(receiver, HeapObject::kMapOffset));
+ __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
+ __ cmp(scratch, Operand(JS_ARRAY_TYPE));
+ __ b(ne, miss_label);
+
+ // Load length directly from the JS array.
+ __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset));
+ __ Ret();
+}
+
+
+void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind)
{
+ ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC);
+ Code* code = NULL;
+ if (kind == Code::LOAD_IC) {
+ code = Builtins::builtin(Builtins::LoadIC_Miss);
+ } else {
+ code = Builtins::builtin(Builtins::KeyedLoadIC_Miss);
+ }
+
+ Handle<Code> ic(code);
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+}
+
+
#undef __
#define __ masm()->
@@ -633,20 +768,9 @@
__ ldr(r0, MemOperand(sp, 0));
- // Check that the receiver isn't a smi.
- __ tst(r0, Operand(kSmiTagMask));
- __ b(eq, &miss);
-
- // Check that the maps haven't changed.
- Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
- GenerateFastPropertyLoad(masm(), r0, reg, holder, index);
- __ Ret();
-
- // Handle load cache miss.
+ GenerateLoadField(masm(), object, holder, r0, r3, r1, index, &miss);
__ bind(&miss);
- __ ldr(r0, MemOperand(sp)); // restore receiver
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
// Return the generated code.
return GetCode(FIELD);
@@ -666,29 +790,9 @@
Label miss;
__ ldr(r0, MemOperand(sp, 0));
- // Check that the receiver isn't a smi.
- __ tst(r0, Operand(kSmiTagMask));
- __ b(eq, &miss);
-
- // Check that the maps haven't changed.
- Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
- // Push the arguments on the JS stack of the caller.
- __ push(r0); // receiver
- __ mov(ip, Operand(Handle<AccessorInfo>(callback))); // callback data
- __ push(ip);
- __ push(r2); // name
- __ push(reg); // holder
-
- // Do tail-call to the runtime system.
- ExternalReference load_callback_property =
- ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
- __ TailCallRuntime(load_callback_property, 4);
-
- // Handle load cache miss.
+ GenerateLoadCallback(masm(), object, holder, r0, r2, r3, r1, callback,
&miss);
__ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
// Return the generated code.
return GetCode(CALLBACKS);
@@ -708,21 +812,10 @@
Label miss;
__ ldr(r0, MemOperand(sp, 0));
- // Check that the receiver isn't a smi.
- __ tst(r0, Operand(kSmiTagMask));
- __ b(eq, &miss);
-
- // Check that the maps haven't changed.
- Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
- // Return the constant value.
- __ mov(r0, Operand(Handle<Object>(value)));
- __ Ret();
- // Handle load cache miss.
+ GenerateLoadConstant(masm(), object, holder, r0, r3, r1, value, &miss);
__ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
// Return the generated code.
return GetCode(CONSTANT_FUNCTION);
@@ -742,27 +835,10 @@
Label miss;
__ ldr(r0, MemOperand(sp, 0));
- // Check that the receiver isn't a smi.
- __ tst(r0, Operand(kSmiTagMask));
- __ b(eq, &miss);
-
- // Check that the maps haven't changed.
- Register reg = __ CheckMaps(object, r0, holder, r3, r1, &miss);
-
- // Push the arguments on the JS stack of the caller.
- __ push(r0); // receiver
- __ push(reg); // holder
- __ push(r2); // name
-
- // Do tail-call to the runtime system.
- ExternalReference load_ic_property =
- ExternalReference(IC_Utility(IC::kLoadInterceptorProperty));
- __ TailCallRuntime(load_ic_property, 3);
- // Handle load cache miss.
+ GenerateLoadInterceptor(masm(), object, holder, r0, r2, r3, r1, &miss);
__ bind(&miss);
- Handle<Code> ic(Builtins::builtin(Builtins::LoadIC_Miss));
- __ Jump(ic, RelocInfo::CODE_TARGET);
+ GenerateLoadMiss(masm(), Code::LOAD_IC);
// Return the generated code.
return GetCode(INTERCEPTOR);
@@ -775,8 +851,25 @@
JSObject* receiver,
JSObject* holder,
int index) {
- UNIMPLEMENTED();
- return Heap::undefined_value();
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+ // -----------------------------------
+ HandleScope scope;
+ Label miss;
+
+ __ ldr(r2, MemOperand(sp, 0));
+ __ ldr(r0, MemOperand(sp, kPointerSize));
+
+ __ cmp(r2, Operand(Handle<String>(name)));
+ __ b(ne, &miss);
+
+ GenerateLoadField(masm(), receiver, holder, r0, r3, r1, index, &miss);
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+ return GetCode(FIELD);
}
@@ -784,8 +877,26 @@
JSObject* receiver,
JSObject* holder,
AccessorInfo* callback)
{
- UNIMPLEMENTED();
- return Heap::undefined_value();
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+ // -----------------------------------
+ HandleScope scope;
+ Label miss;
+
+ __ ldr(r2, MemOperand(sp, 0));
+ __ ldr(r0, MemOperand(sp, kPointerSize));
+
+ __ cmp(r2, Operand(Handle<String>(name)));
+ __ b(ne, &miss);
+
+ GenerateLoadCallback(masm(), receiver, holder, r0, r2, r3,
+ r1, callback, &miss);
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+ return GetCode(CALLBACKS);
}
@@ -793,45 +904,126 @@
JSObject* receiver,
JSObject* holder,
Object* value) {
- UNIMPLEMENTED();
- return Heap::undefined_value();
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+ // -----------------------------------
+ HandleScope scope;
+ Label miss;
+
+ // Check the key is the cached one
+ __ ldr(r2, MemOperand(sp, 0));
+ __ ldr(r0, MemOperand(sp, kPointerSize));
+
+ __ cmp(r2, Operand(Handle<String>(name)));
+ __ b(ne, &miss);
+
+ GenerateLoadConstant(masm(), receiver, holder, r0, r3, r1, value, &miss);
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+ // Return the generated code.
+ return GetCode(CONSTANT_FUNCTION);
}
Object* KeyedLoadStubCompiler::CompileLoadInterceptor(JSObject* receiver,
JSObject* holder,
String* name) {
- UNIMPLEMENTED();
- return Heap::undefined_value();
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+ // -----------------------------------
+ HandleScope scope;
+ Label miss;
+
+ // Check the key is the cached one
+ __ ldr(r2, MemOperand(sp, 0));
+ __ ldr(r0, MemOperand(sp, kPointerSize));
+
+ __ cmp(r2, Operand(Handle<String>(name)));
+ __ b(ne, &miss);
+
+ GenerateLoadInterceptor(masm(), receiver, holder, r0, r2, r3, r1, &miss);
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+ return GetCode(INTERCEPTOR);
}
Object* KeyedLoadStubCompiler::CompileLoadArrayLength(String* name) {
- UNIMPLEMENTED();
- return Heap::undefined_value();
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+ // -----------------------------------
+ HandleScope scope;
+ Label miss;
+
+ // Check the key is the cached one
+ __ ldr(r2, MemOperand(sp, 0));
+ __ ldr(r0, MemOperand(sp, kPointerSize));
+
+ __ cmp(r2, Operand(Handle<String>(name)));
+ __ b(ne, &miss);
+
+ GenerateLoadArrayLength(masm(), r0, r3, &miss);
+ __ bind(&miss);
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+ return GetCode(CALLBACKS);
}
+// TODO(1224671): implement the fast case.
Object* KeyedLoadStubCompiler::CompileLoadStringLength(String* name) {
- UNIMPLEMENTED();
- return Heap::undefined_value();
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+ // -----------------------------------
+ HandleScope scope;
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+ return GetCode(CALLBACKS);
}
+// TODO(1224671): implement the fast case.
Object* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
- UNIMPLEMENTED();
- return Heap::undefined_value();
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- sp[0] : key
+ // -- sp[4] : receiver
+ // -----------------------------------
+ HandleScope scope;
+ GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
+
+ return GetCode(CALLBACKS);
}
+// TODO(1224671): implement the fast case.
Object* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
int index,
Map* transition,
String* name) {
- UNIMPLEMENTED();
- return Heap::undefined_value();
-}
+ // ----------- S t a t e -------------
+ // -- r0 : value
+ // -- r2 : name
+ // -- lr : return address
+ // -- [sp] : receiver
+ // -----------------------------------
+ HandleScope scope;
+ Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
+ __ Jump(ic, RelocInfo::CODE_TARGET);
+ // Return the generated code.
+ return GetCode(transition == NULL ? FIELD : MAP_TRANSITION);
+}
#undef __
Modified: branches/experimental/toiger/src/top.cc
==============================================================================
--- branches/experimental/toiger/src/top.cc (original)
+++ branches/experimental/toiger/src/top.cc Fri Nov 14 04:47:25 2008
@@ -253,7 +253,30 @@
}
+// There are cases where the C stack is separated from JS stack (ARM
simulator).
+// To figure out the order of top-most JS try-catch handler and the
top-most C
+// try-catch handler, the C try-catch handler keeps a reference to the
top-most
+// JS try_catch handler when it was created.
+//
+// Here is a picture to explain the idea:
+// Top::thread_local_.handler_
Top::thread_local_.try_catch_handler_
+//
+// | |
+// v v
+//
+// | JS handler | | C try_catch handler |
+// | next |--+ +-------- | js_handler_ |
+// | | | next_ |--+
+// | | |
+// | JS handler |--+ <---------+ |
+// | next |
+//
+// If the top-most JS try-catch handler is not equal to
+// Top::thread_local_.try_catch_handler_.js_handler_, it means the JS
handler
+// is on the top. Otherwise, it means the C try-catch handler is on the
top.
+//
void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
+ that->js_handler_ = thread_local_.handler_; // casted to void*
thread_local_.try_catch_handler_ = that;
}
@@ -719,8 +742,7 @@
// address of the external handler so we can compare the address to
// determine which one is closer to the top of the stack.
bool has_external_handler = (thread_local_.try_catch_handler_ != NULL);
- Address external_handler_address =
- reinterpret_cast<Address>(thread_local_.try_catch_handler_);
+ v8::TryCatch* try_catch = thread_local_.try_catch_handler_;
// NOTE: The stack is assumed to grown towards lower addresses. If
// the handler is at a higher address than the external address it
@@ -732,10 +754,12 @@
}
// The exception has been externally caught if and only if there is
- // an external handler which is above any JavaScript try-catch but NOT
- // try-finally handlers.
+ // an external handler which is on top of the top-most try-catch
+ // handler.
+ //
+ // See comments in RegisterTryCatchHandler for details.
*is_caught_externally = has_external_handler &&
- (handler == NULL || handler->address() > external_handler_address);
+ (handler == NULL || handler == try_catch->js_handler_);
// If we have a try-catch handler then the exception is caught in
// JavaScript code.
@@ -745,7 +769,7 @@
// exception if it isn't caught by JavaScript code.
if (!has_external_handler) return is_uncaught_by_js;
- if (is_uncaught_by_js || handler->address() > external_handler_address) {
+ if (is_uncaught_by_js || handler == try_catch->js_handler_) {
// Only report the exception if the external handler is verbose.
return thread_local_.try_catch_handler_->is_verbose_;
} else {
Modified: branches/experimental/toiger/test/cctest/cctest.status
==============================================================================
--- branches/experimental/toiger/test/cctest/cctest.status (original)
+++ branches/experimental/toiger/test/cctest/cctest.status Fri Nov 14
04:47:25 2008
@@ -34,7 +34,6 @@
test-debug: SKIP
test-serialize: SKIP
-test-api: SKIP
# BUG(113): Test seems flaky on ARM.
test-spaces/LargeObjectSpace: PASS || FAIL
Modified: branches/experimental/toiger/tools/visual_studio/arm.vsprops
==============================================================================
--- branches/experimental/toiger/tools/visual_studio/arm.vsprops
(original)
+++ branches/experimental/toiger/tools/visual_studio/arm.vsprops Fri Nov
14
04:47:25 2008
@@ -7,5 +7,6 @@
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="ARM"
+ DisableSpecificWarnings="4996"
/>
</VisualStudioPropertySheet>
--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---