Improved frame merge code generated by the code generator.
Optimized String.prototype.replace.
Implemented __defineGetter__ and __defineSetter__ for properties with integer keys on non-array objects.
Improved debugger and profiler support.
Fixed a number of portability issues to allow compilation for smaller ARM devices.
Exposed object cloning through the API.
Implemented hidden properties. This is used to expose an identity hash for objects through the API.
Implemented restarting of regular expressions if their input string changes representation during preemption.
Fixed a code generator bug that could cause assignments in loops to be ignored if using continue to break out of the loop (issue 284).
git-svn-id: http://v8.googlecode.com/svn/trunk@1598 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/frames.cc b/src/frames.cc
index 3270797..763ff48 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -66,23 +66,32 @@
#define INITIALIZE_SINGLETON(type, field) field##_(this),
StackFrameIterator::StackFrameIterator()
: STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
- frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) {
+ frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()),
+ fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
Reset();
}
StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
: STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
- frame_(NULL), handler_(NULL), thread_(t) {
+ frame_(NULL), handler_(NULL), thread_(t),
+ fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
Reset();
}
-StackFrameIterator::StackFrameIterator(bool reset)
+StackFrameIterator::StackFrameIterator(bool use_top, Address fp, Address sp)
: STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
- frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) {
- if (reset) Reset();
+ frame_(NULL), handler_(NULL),
+ thread_(use_top ? Top::GetCurrentThread() : NULL),
+ fp_(use_top ? NULL : fp), sp_(sp),
+ advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
+ &StackFrameIterator::AdvanceWithoutHandler) {
+ if (use_top || fp != NULL) {
+ Reset();
+ }
}
+
#undef INITIALIZE_SINGLETON
-void StackFrameIterator::Advance() {
+void StackFrameIterator::AdvanceWithHandler() {
ASSERT(!done());
// Compute the state of the calling frame before restoring
// callee-saved registers and unwinding handlers. This allows the
@@ -105,17 +114,45 @@
}
-void StackFrameIterator::Reset() {
- Address fp = Top::c_entry_fp(thread_);
+void StackFrameIterator::AdvanceWithoutHandler() {
+ // A simpler version of Advance which doesn't care about handler.
+ ASSERT(!done());
StackFrame::State state;
- StackFrame::Type type = ExitFrame::GetStateForFramePointer(fp, &state);
+ StackFrame::Type type = frame_->GetCallerState(&state);
frame_ = SingletonFor(type, &state);
- handler_ = StackHandler::FromAddress(Top::handler(thread_));
+}
+
+
+void StackFrameIterator::Reset() {
+ StackFrame::State state;
+ StackFrame::Type type;
+ if (thread_ != NULL) {
+ type = ExitFrame::GetStateForFramePointer(Top::c_entry_fp(thread_), &state);
+ handler_ = StackHandler::FromAddress(Top::handler(thread_));
+ } else {
+ ASSERT(fp_ != NULL);
+ state.fp = fp_;
+ state.sp = sp_;
+ state.pc_address =
+ reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
+ type = StackFrame::ComputeType(&state);
+ if (SingletonFor(type) == NULL) return;
+ }
+ frame_ = SingletonFor(type, &state);
}
StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
StackFrame::State* state) {
+ if (type == StackFrame::NONE) return NULL;
+ StackFrame* result = SingletonFor(type);
+ ASSERT(result != NULL);
+ result->state_ = *state;
+ return result;
+}
+
+
+StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
#define FRAME_TYPE_CASE(type, field) \
case StackFrame::type: result = &field##_; break;
@@ -125,8 +162,6 @@
STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
default: break;
}
- ASSERT(result != NULL);
- result->state_ = *state;
return result;
#undef FRAME_TYPE_CASE
@@ -154,29 +189,50 @@
SafeStackFrameIterator::SafeStackFrameIterator(
- Address low_bound, Address high_bound) :
+ Address fp, Address sp, Address low_bound, Address high_bound) :
low_bound_(low_bound), high_bound_(high_bound),
- is_working_iterator_(IsInBounds(low_bound, high_bound,
- Top::c_entry_fp(Top::GetCurrentThread()))),
- iteration_done_(!is_working_iterator_), iterator_(is_working_iterator_) {
+ is_valid_top_(
+ IsWithinBounds(low_bound, high_bound,
+ Top::c_entry_fp(Top::GetCurrentThread())) &&
+ Top::handler(Top::GetCurrentThread()) != NULL),
+ is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
+ is_working_iterator_(is_valid_top_ || is_valid_fp_),
+ iteration_done_(!is_working_iterator_),
+ iterator_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
}
void SafeStackFrameIterator::Advance() {
ASSERT(is_working_iterator_);
ASSERT(!done());
- StackFrame* frame = iterator_.frame();
- iteration_done_ =
- !IsGoodStackAddress(frame->sp()) || !IsGoodStackAddress(frame->fp());
- if (!iteration_done_) {
- iterator_.Advance();
- if (!iterator_.done()) {
- // Check that we have actually moved to the previous frame in the stack
- StackFrame* prev_frame = iterator_.frame();
- iteration_done_ =
- prev_frame->sp() < frame->sp() || prev_frame->fp() < frame->fp();
- }
- }
+ StackFrame* last_frame = iterator_.frame();
+ Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
+ // Before advancing to the next stack frame, perform pointer validity tests
+ iteration_done_ = !IsValidFrame(last_frame) || !IsValidCaller(last_frame);
+ if (iteration_done_) return;
+
+ iterator_.Advance();
+ if (iterator_.done()) return;
+ // Check that we have actually moved to the previous frame in the stack
+ StackFrame* prev_frame = iterator_.frame();
+ iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
+}
+
+
+bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
+ return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()) &&
+ // JavaScriptFrame uses function shared info to advance, hence it must
+ // point to a valid function object.
+ (!frame->is_java_script() ||
+ reinterpret_cast<JavaScriptFrame*>(frame)->is_at_function());
+}
+
+
+bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
+ StackFrame::State state;
+ frame->ComputeCallerState(&state);
+ return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
+ iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
}
@@ -193,9 +249,9 @@
#ifdef ENABLE_LOGGING_AND_PROFILING
SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
- Address low_bound, Address high_bound) :
- SafeJavaScriptFrameIterator(low_bound, high_bound) {
- if (!done() && !frame()->function()->IsJSFunction()) Advance();
+ Address fp, Address sp, Address low_bound, Address high_bound) :
+ SafeJavaScriptFrameIterator(fp, sp, low_bound, high_bound) {
+ if (!done() && !frame()->is_at_function()) Advance();
}
@@ -203,7 +259,7 @@
while (true) {
SafeJavaScriptFrameIterator::Advance();
if (done()) return;
- if (frame()->function()->IsJSFunction()) return;
+ if (frame()->is_at_function()) return;
}
}
#endif
@@ -279,11 +335,22 @@
}
+StackFrame::Type StackFrame::GetCallerState(State* state) const {
+ ComputeCallerState(state);
+ return ComputeType(state);
+}
+
+
Code* EntryFrame::code() const {
return Heap::js_entry_code();
}
+void EntryFrame::ComputeCallerState(State* state) const {
+ GetCallerState(state);
+}
+
+
StackFrame::Type EntryFrame::GetCallerState(State* state) const {
const int offset = EntryFrameConstants::kCallerFPOffset;
Address fp = Memory::Address_at(this->fp() + offset);
@@ -301,13 +368,12 @@
}
-StackFrame::Type ExitFrame::GetCallerState(State* state) const {
+void ExitFrame::ComputeCallerState(State* state) const {
// Setup the caller state.
state->sp = pp();
state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
state->pc_address
= reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
- return ComputeType(state);
}
@@ -338,11 +404,10 @@
}
-StackFrame::Type StandardFrame::GetCallerState(State* state) const {
+void StandardFrame::ComputeCallerState(State* state) const {
state->sp = caller_sp();
state->fp = caller_fp();
state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
- return ComputeType(state);
}