Version 3.20.0
Migrated several tests from blink to V8 repository.
Allowed users of the V8 API to distinguish between unset and undefined HiddenValues (issue 2746).
Deprecated old style callbacks in the V8 API.
Turned on parallel recompilation.
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@15386 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/frames.cc b/src/frames.cc
index 53f5108..edd5ddd 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -43,19 +43,8 @@
namespace internal {
-static ReturnAddressLocationResolver return_address_location_resolver = NULL;
-
-
-// Resolves pc_address through the resolution address function if one is set.
-static inline Address* ResolveReturnAddressLocation(Address* pc_address) {
- if (return_address_location_resolver == NULL) {
- return pc_address;
- } else {
- return reinterpret_cast<Address*>(
- return_address_location_resolver(
- reinterpret_cast<uintptr_t>(pc_address)));
- }
-}
+ReturnAddressLocationResolver
+ StackFrame::return_address_location_resolver_ = NULL;
// Iterator that supports traversing the stack handlers of a
@@ -88,39 +77,29 @@
#define INITIALIZE_SINGLETON(type, field) field##_(this),
-StackFrameIterator::StackFrameIterator(Isolate* isolate)
+StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
+ bool can_access_heap_objects)
: isolate_(isolate),
STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
frame_(NULL), handler_(NULL),
- thread_(isolate_->thread_local_top()),
- fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
- Reset();
+ can_access_heap_objects_(can_access_heap_objects) {
}
-StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
- : isolate_(isolate),
- STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
- frame_(NULL), handler_(NULL), thread_(t),
- fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
- Reset();
-}
-StackFrameIterator::StackFrameIterator(Isolate* isolate,
- bool use_top, Address fp, Address sp)
- : isolate_(isolate),
- STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
- frame_(NULL), handler_(NULL),
- thread_(use_top ? isolate_->thread_local_top() : 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::AdvanceWithHandler() {
+StackFrameIterator::StackFrameIterator(Isolate* isolate)
+ : StackFrameIteratorBase(isolate, true) {
+ Reset(isolate->thread_local_top());
+}
+
+
+StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
+ : StackFrameIteratorBase(isolate, true) {
+ Reset(t);
+}
+
+
+void StackFrameIterator::Advance() {
ASSERT(!done());
// Compute the state of the calling frame before restoring
// callee-saved registers and unwinding handlers. This allows the
@@ -143,37 +122,17 @@
}
-void StackFrameIterator::AdvanceWithoutHandler() {
- // A simpler version of Advance which doesn't care about handler.
- ASSERT(!done());
+void StackFrameIterator::Reset(ThreadLocalTop* top) {
StackFrame::State state;
- StackFrame::Type type = frame_->GetCallerState(&state);
- frame_ = SingletonFor(type, &state);
-}
-
-
-void StackFrameIterator::Reset() {
- StackFrame::State state;
- StackFrame::Type type;
- if (thread_ != NULL) {
- type = ExitFrame::GetStateForFramePointer(
- Isolate::c_entry_fp(thread_), &state);
- handler_ = StackHandler::FromAddress(
- Isolate::handler(thread_));
- } else {
- ASSERT(fp_ != NULL);
- state.fp = fp_;
- state.sp = sp_;
- state.pc_address = ResolveReturnAddressLocation(
- reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)));
- type = StackFrame::ComputeType(isolate(), &state);
- }
+ StackFrame::Type type = ExitFrame::GetStateForFramePointer(
+ Isolate::c_entry_fp(top), &state);
+ handler_ = StackHandler::FromAddress(Isolate::handler(top));
if (SingletonFor(type) == NULL) return;
frame_ = SingletonFor(type, &state);
}
-StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
+StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
StackFrame::State* state) {
if (type == StackFrame::NONE) return NULL;
StackFrame* result = SingletonFor(type);
@@ -183,7 +142,7 @@
}
-StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
+StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
#define FRAME_TYPE_CASE(type, field) \
case StackFrame::type: result = &field##_; break;
@@ -202,6 +161,33 @@
// -------------------------------------------------------------------------
+JavaScriptFrameIterator::JavaScriptFrameIterator(
+ Isolate* isolate, StackFrame::Id id)
+ : iterator_(isolate) {
+ while (!done()) {
+ Advance();
+ if (frame()->id() == id) return;
+ }
+}
+
+
+void JavaScriptFrameIterator::Advance() {
+ do {
+ iterator_.Advance();
+ } while (!iterator_.done() && !iterator_.frame()->is_java_script());
+}
+
+
+void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
+ if (!frame()->has_adapted_arguments()) return;
+ iterator_.Advance();
+ ASSERT(iterator_.frame()->is_arguments_adaptor());
+}
+
+
+// -------------------------------------------------------------------------
+
+
StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
: JavaScriptFrameIterator(isolate) {
if (!done() && !IsValidFrame()) Advance();
@@ -228,85 +214,61 @@
// -------------------------------------------------------------------------
-bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
- if (!validator_.IsValid(fp)) return false;
- Address sp = ExitFrame::ComputeStackPointer(fp);
- if (!validator_.IsValid(sp)) return false;
- StackFrame::State state;
- ExitFrame::FillState(fp, sp, &state);
- if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
- return false;
- }
- return *state.pc_address != NULL;
-}
-
-
-SafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer(
- Isolate* isolate)
- : isolate_(isolate) {
- isolate_->set_safe_stack_iterator_counter(
- isolate_->safe_stack_iterator_counter() + 1);
-}
-
-
-SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
- isolate_->set_safe_stack_iterator_counter(
- isolate_->safe_stack_iterator_counter() - 1);
-}
-
-
SafeStackFrameIterator::SafeStackFrameIterator(
Isolate* isolate,
Address fp, Address sp, Address low_bound, Address high_bound) :
- maintainer_(isolate),
- stack_validator_(low_bound, high_bound),
- is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
- is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
- is_working_iterator_(is_valid_top_ || is_valid_fp_),
- iteration_done_(!is_working_iterator_),
- iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
-}
-
-bool SafeStackFrameIterator::is_active(Isolate* isolate) {
- return isolate->safe_stack_iterator_counter() > 0;
-}
-
-
-bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
- Address low_bound, Address high_bound) {
+ StackFrameIteratorBase(isolate, false),
+ low_bound_(low_bound), high_bound_(high_bound) {
+ StackFrame::State state;
+ StackFrame::Type type;
ThreadLocalTop* top = isolate->thread_local_top();
+ if (IsValidTop(top)) {
+ type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
+ } else if (IsValidStackAddress(fp)) {
+ ASSERT(fp != NULL);
+ state.fp = fp;
+ state.sp = sp;
+ state.pc_address = StackFrame::ResolveReturnAddressLocation(
+ reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
+ type = StackFrame::ComputeType(this, &state);
+ } else {
+ return;
+ }
+ if (SingletonFor(type) == NULL) return;
+ frame_ = SingletonFor(type, &state);
+
+ if (!done()) Advance();
+}
+
+
+bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
Address fp = Isolate::c_entry_fp(top);
- ExitFrameValidator validator(low_bound, high_bound);
- if (!validator.IsValidFP(fp)) return false;
+ if (!IsValidExitFrame(fp)) return false;
+ // There should be at least one JS_ENTRY stack handler.
return Isolate::handler(top) != NULL;
}
-void SafeStackFrameIterator::Advance() {
- ASSERT(is_working_iterator_);
+void SafeStackFrameIterator::AdvanceOneFrame() {
ASSERT(!done());
- StackFrame* last_frame = iterator_.frame();
+ StackFrame* last_frame = 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) ||
- !CanIterateHandles(last_frame, iterator_.handler()) ||
- !IsValidCaller(last_frame);
- if (iteration_done_) return;
+ // Before advancing to the next stack frame, perform pointer validity tests.
+ if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
+ frame_ = NULL;
+ 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;
-}
+ // Advance to the previous frame.
+ StackFrame::State state;
+ StackFrame::Type type = frame_->GetCallerState(&state);
+ frame_ = SingletonFor(type, &state);
+ if (frame_ == NULL) return;
-
-bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
- StackHandler* handler) {
- // If StackIterator iterates over StackHandles, verify that
- // StackHandlerIterator can be instantiated (see StackHandlerIterator
- // constructor.)
- return !is_valid_top_ || (frame->sp() <= handler->address());
+ // Check that we have actually moved to the previous frame in the stack.
+ if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
+ frame_ = NULL;
+ }
}
@@ -323,8 +285,7 @@
// sure that caller FP address is valid.
Address caller_fp = Memory::Address_at(
frame->fp() + EntryFrameConstants::kCallerFPOffset);
- ExitFrameValidator validator(stack_validator_);
- if (!validator.IsValidFP(caller_fp)) return false;
+ if (!IsValidExitFrame(caller_fp)) return false;
} else if (frame->is_arguments_adaptor()) {
// See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
// the number of arguments is stored on stack as Smi. We need to check
@@ -337,14 +298,28 @@
}
frame->ComputeCallerState(&state);
return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
- iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
+ SingletonFor(frame->GetCallerState(&state)) != NULL;
}
-void SafeStackFrameIterator::Reset() {
- if (is_working_iterator_) {
- iterator_.Reset();
- iteration_done_ = false;
+bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
+ if (!IsValidStackAddress(fp)) return false;
+ Address sp = ExitFrame::ComputeStackPointer(fp);
+ if (!IsValidStackAddress(sp)) return false;
+ StackFrame::State state;
+ ExitFrame::FillState(fp, sp, &state);
+ if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) {
+ return false;
+ }
+ return *state.pc_address != NULL;
+}
+
+
+void SafeStackFrameIterator::Advance() {
+ while (true) {
+ AdvanceOneFrame();
+ if (done()) return;
+ if (frame_->is_java_script()) return;
}
}
@@ -352,23 +327,6 @@
// -------------------------------------------------------------------------
-SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
- Isolate* isolate,
- Address fp, Address sp, Address low_bound, Address high_bound) :
- SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
- if (!done() && !frame()->is_java_script()) Advance();
-}
-
-
-void SafeStackTraceFrameIterator::Advance() {
- while (true) {
- SafeJavaScriptFrameIterator::Advance();
- if (done()) return;
- if (frame()->is_java_script()) return;
- }
-}
-
-
Code* StackFrame::GetSafepointData(Isolate* isolate,
Address inner_pointer,
SafepointEntry* safepoint_entry,
@@ -420,12 +378,13 @@
void StackFrame::SetReturnAddressLocationResolver(
ReturnAddressLocationResolver resolver) {
- ASSERT(return_address_location_resolver == NULL);
- return_address_location_resolver = resolver;
+ ASSERT(return_address_location_resolver_ == NULL);
+ return_address_location_resolver_ = resolver;
}
-StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
+StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
+ State* state) {
ASSERT(state->fp != NULL);
if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
return ARGUMENTS_ADAPTOR;
@@ -440,8 +399,9 @@
// frames as normal JavaScript frames to avoid having to look
// into the heap to determine the state. This is safe as long
// as nobody tries to GC...
- if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
- Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
+ if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT;
+ Code::Kind kind = GetContainingCode(iterator->isolate(),
+ *(state->pc_address))->kind();
ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
}
@@ -449,10 +409,16 @@
}
+#ifdef DEBUG
+bool StackFrame::can_access_heap_objects() const {
+ return iterator_->can_access_heap_objects_;
+}
+#endif
+
StackFrame::Type StackFrame::GetCallerState(State* state) const {
ComputeCallerState(state);
- return ComputeType(isolate(), state);
+ return ComputeType(iterator_, state);
}
@@ -545,6 +511,11 @@
}
+Address ExitFrame::ComputeStackPointer(Address fp) {
+ return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
+}
+
+
void ExitFrame::FillState(Address fp, Address sp, State* state) {
state->sp = sp;
state->fp = fp;
@@ -607,7 +578,7 @@
void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const {
// Make sure that we're not doing "safe" stack frame iteration. We cannot
// possibly find pointers in optimized frames in that state.
- ASSERT(!SafeStackFrameIterator::is_active(isolate()));
+ ASSERT(can_access_heap_objects());
// Compute the safepoint information.
unsigned stack_slots = 0;
@@ -734,12 +705,12 @@
Code* JavaScriptFrame::unchecked_code() const {
JSFunction* function = JSFunction::cast(this->function());
- return function->unchecked_code();
+ return function->code();
}
int JavaScriptFrame::GetNumberOfIncomingArguments() const {
- ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
+ ASSERT(can_access_heap_objects() &&
isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
JSFunction* function = JSFunction::cast(this->function());