Revision: 5472
Author: [email protected]
Date: Thu Sep 16 03:01:13 2010
Log: Merge r5467..r5469 into branches/2.3.
A fix for profiler stack iterator (and subsequent build fixes).
BUG=crbug/55565
Review URL: http://codereview.chromium.org/3410012
http://code.google.com/p/v8/source/detail?r=5472
Modified:
/branches/2.3/src/arm/frames-arm.cc
/branches/2.3/src/frames.cc
/branches/2.3/src/frames.h
/branches/2.3/src/ia32/frames-ia32.cc
/branches/2.3/src/log.cc
/branches/2.3/src/mips/frames-mips.cc
/branches/2.3/src/version.cc
/branches/2.3/src/x64/frames-x64.cc
/branches/2.3/test/cctest/test-log-stack-tracer.cc
=======================================
--- /branches/2.3/src/arm/frames-arm.cc Mon Aug 30 23:45:16 2010
+++ /branches/2.3/src/arm/frames-arm.cc Thu Sep 16 03:01:13 2010
@@ -52,17 +52,8 @@
}
-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State*
state) {
- if (fp == 0) return NONE;
- // Compute frame type and stack pointer.
- Address sp = fp + ExitFrameConstants::kSPOffset;
-
- // Fill in the state.
- state->sp = sp;
- state->fp = fp;
- state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
- ASSERT(*state->pc_address != NULL);
- return EXIT;
+Address ExitFrame::ComputeStackPointer(Address fp) {
+ return fp + ExitFrameConstants::kSPOffset;
}
=======================================
--- /branches/2.3/src/frames.cc Wed Aug 18 00:45:01 2010
+++ /branches/2.3/src/frames.cc Thu Sep 16 03:01:13 2010
@@ -139,8 +139,8 @@
state.pc_address =
reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_));
type = StackFrame::ComputeType(&state);
- if (SingletonFor(type) == NULL) return;
- }
+ }
+ if (SingletonFor(type) == NULL) return;
frame_ = SingletonFor(type, &state);
}
@@ -199,18 +199,36 @@
//
-------------------------------------------------------------------------
+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::SafeStackFrameIterator(
Address fp, Address sp, Address low_bound, Address high_bound) :
- low_bound_(low_bound), high_bound_(high_bound),
- is_valid_top_(
- IsWithinBounds(low_bound, high_bound,
- Top::c_entry_fp(Top::GetCurrentThread())) &&
- Top::handler(Top::GetCurrentThread()) != NULL),
+ stack_validator_(low_bound, high_bound),
+ is_valid_top_(IsValidTop(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_(is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
}
+
+
+bool SafeStackFrameIterator::IsValidTop(Address low_bound, Address
high_bound) {
+ Address fp = Top::c_entry_fp(Top::GetCurrentThread());
+ ExitFrameValidator validator(low_bound, high_bound);
+ if (!validator.IsValidFP(fp)) return false;
+ return Top::handler(Top::GetCurrentThread()) != NULL;
+}
void SafeStackFrameIterator::Advance() {
@@ -254,9 +272,8 @@
// sure that caller FP address is valid.
Address caller_fp = Memory::Address_at(
frame->fp() + EntryFrameConstants::kCallerFPOffset);
- if (!IsValidStackAddress(caller_fp)) {
- return false;
- }
+ ExitFrameValidator validator(stack_validator_);
+ if (!validator.IsValidFP(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
@@ -428,6 +445,22 @@
Address ExitFrame::GetCallerStackPointer() const {
return fp() + ExitFrameConstants::kCallerSPDisplacement;
}
+
+
+StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State*
state) {
+ if (fp == 0) return NONE;
+ Address sp = ComputeStackPointer(fp);
+ FillState(fp, sp, state);
+ ASSERT(*state->pc_address != NULL);
+ return EXIT;
+}
+
+
+void ExitFrame::FillState(Address fp, Address sp, State* state) {
+ state->sp = sp;
+ state->fp = fp;
+ state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
+}
Address StandardFrame::GetExpressionAddress(int n) const {
=======================================
--- /branches/2.3/src/frames.h Mon Aug 30 23:45:16 2010
+++ /branches/2.3/src/frames.h Thu Sep 16 03:01:13 2010
@@ -120,6 +120,13 @@
NO_ID = 0
};
+ struct State {
+ State() : sp(NULL), fp(NULL), pc_address(NULL) { }
+ Address sp;
+ Address fp;
+ Address* pc_address;
+ };
+
// Copy constructor; it breaks the connection to host iterator.
StackFrame(const StackFrame& original) {
this->state_ = original.state_;
@@ -179,12 +186,6 @@
int index) const { }
protected:
- struct State {
- Address sp;
- Address fp;
- Address* pc_address;
- };
-
explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator)
{ }
virtual ~StackFrame() { }
@@ -300,6 +301,8 @@
// pointer. Used when constructing the first stack frame seen by an
// iterator and the frames following entry frames.
static Type GetStateForFramePointer(Address fp, State* state);
+ static Address ComputeStackPointer(Address fp);
+ static void FillState(Address fp, Address sp, State* state);
protected:
explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator)
{ }
@@ -433,6 +436,7 @@
inline Object* function_slot_object() const;
friend class StackFrameIterator;
+ friend class StackTracer;
};
@@ -642,15 +646,38 @@
}
private:
+ class StackAddressValidator {
+ public:
+ StackAddressValidator(Address low_bound, Address high_bound)
+ : low_bound_(low_bound), high_bound_(high_bound) { }
+ bool IsValid(Address addr) const {
+ return IsWithinBounds(low_bound_, high_bound_, addr);
+ }
+ private:
+ Address low_bound_;
+ Address high_bound_;
+ };
+
+ class ExitFrameValidator {
+ public:
+ explicit ExitFrameValidator(const StackAddressValidator& validator)
+ : validator_(validator) { }
+ ExitFrameValidator(Address low_bound, Address high_bound)
+ : validator_(low_bound, high_bound) { }
+ bool IsValidFP(Address fp);
+ private:
+ StackAddressValidator validator_;
+ };
+
bool IsValidStackAddress(Address addr) const {
- return IsWithinBounds(low_bound_, high_bound_, addr);
+ return stack_validator_.IsValid(addr);
}
bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
bool IsValidFrame(StackFrame* frame) const;
bool IsValidCaller(StackFrame* frame);
-
- Address low_bound_;
- Address high_bound_;
+ static bool IsValidTop(Address low_bound, Address high_bound);
+
+ StackAddressValidator stack_validator_;
const bool is_valid_top_;
const bool is_valid_fp_;
const bool is_working_iterator_;
=======================================
--- /branches/2.3/src/ia32/frames-ia32.cc Mon Aug 30 23:45:16 2010
+++ /branches/2.3/src/ia32/frames-ia32.cc Thu Sep 16 03:01:13 2010
@@ -50,16 +50,8 @@
}
-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State*
state) {
- if (fp == 0) return NONE;
- // Compute the stack pointer.
- Address sp = Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
- // Fill in the state.
- state->fp = fp;
- state->sp = sp;
- state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
- ASSERT(*state->pc_address != NULL);
- return EXIT;
+Address ExitFrame::ComputeStackPointer(Address fp) {
+ return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
}
=======================================
--- /branches/2.3/src/log.cc Mon Jun 28 04:29:21 2010
+++ /branches/2.3/src/log.cc Thu Sep 16 03:01:13 2010
@@ -170,7 +170,9 @@
SafeStackTraceFrameIterator it(sample->fp, sample->sp,
sample->sp, js_entry_sp);
while (!it.done() && i < TickSample::kMaxFramesCount) {
- sample->stack[i++] = reinterpret_cast<Address>(it.frame()->function());
+ sample->stack[i++] =
+ reinterpret_cast<Address>(it.frame()->function_slot_object()) -
+ kHeapObjectTag;
it.Advance();
}
sample->frames_count = i;
=======================================
--- /branches/2.3/src/mips/frames-mips.cc Fri May 21 05:58:28 2010
+++ /branches/2.3/src/mips/frames-mips.cc Thu Sep 16 03:01:13 2010
@@ -52,9 +52,7 @@
}
-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State*
state) {
- if (fp == 0) return NONE;
- // Compute frame type and stack pointer.
+Address ExitFrame::ComputeStackPointer(Address fp) {
Address sp = fp + ExitFrameConstants::kSPDisplacement;
const int offset = ExitFrameConstants::kCodeOffset;
Object* code = Memory::Object_at(fp + offset);
@@ -62,11 +60,7 @@
if (is_debug_exit) {
sp -= kNumJSCallerSaved * kPointerSize;
}
- // Fill in the state.
- state->sp = sp;
- state->fp = fp;
- state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
- return EXIT;
+ return sp;
}
=======================================
--- /branches/2.3/src/version.cc Tue Sep 7 03:13:55 2010
+++ /branches/2.3/src/version.cc Thu Sep 16 03:01:13 2010
@@ -35,7 +35,7 @@
#define MAJOR_VERSION 2
#define MINOR_VERSION 3
#define BUILD_NUMBER 11
-#define PATCH_LEVEL 6
+#define PATCH_LEVEL 7
#define CANDIDATE_VERSION false
// Define SONAME to have the SCons build the put a specific SONAME into the
=======================================
--- /branches/2.3/src/x64/frames-x64.cc Mon Aug 30 23:45:16 2010
+++ /branches/2.3/src/x64/frames-x64.cc Thu Sep 16 03:01:13 2010
@@ -50,17 +50,10 @@
}
-StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State*
state) {
- if (fp == 0) return NONE;
- // Compute the stack pointer.
- Address sp = Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
- // Fill in the state.
- state->fp = fp;
- state->sp = sp;
- state->pc_address = reinterpret_cast<Address*>(sp - 1 * kPointerSize);
- ASSERT(*state->pc_address != NULL);
- return EXIT;
-}
+Address ExitFrame::ComputeStackPointer(Address fp) {
+ return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
+}
+
int JavaScriptFrame::GetProvidedParametersCount() const {
return ComputeParametersCount();
=======================================
--- /branches/2.3/test/cctest/test-log-stack-tracer.cc Wed Aug 25 08:26:24
2010
+++ /branches/2.3/test/cctest/test-log-stack-tracer.cc Thu Sep 16 03:01:13
2010
@@ -175,21 +175,8 @@
}
-static Local<Value> GetGlobalProperty(const char* name) {
- return env->Global()->Get(String::New(name));
-}
-
-
-static Handle<JSFunction> GetGlobalJSFunction(const char* name) {
- Handle<JSFunction> result(JSFunction::cast(
- *v8::Utils::OpenHandle(*GetGlobalProperty(name))));
- return result;
-}
-
-
-static void CheckObjectIsJSFunction(const char* func_name,
- Address addr) {
- i::Object* obj = reinterpret_cast<i::Object*>(addr);
+static void CheckJSFunctionAtAddress(const char* func_name, Address addr) {
+ i::Object* obj = i::HeapObject::FromAddress(addr);
CHECK(obj->IsJSFunction());
CHECK(JSFunction::cast(obj)->shared()->name()->IsString());
i::SmartPointer<char> found_name =
@@ -264,7 +251,6 @@
#endif
SetGlobalProperty(func_name, v8::ToApi<Value>(func));
- CHECK_EQ(*func, *GetGlobalJSFunction(func_name));
}
@@ -298,13 +284,13 @@
// script [JS]
// JSTrace() [JS]
// JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi]
- // trace(EBP encoded as Smi) [native (extension)]
+ // trace(EBP) [native (extension)]
// DoTrace(EBP) [native]
// StackTracer::Trace
CHECK_GT(sample.frames_count, 1);
// Stack tracing will start from the first JS function,
i.e. "JSFuncDoTrace"
- CheckObjectIsJSFunction("JSFuncDoTrace", sample.stack[0]);
- CheckObjectIsJSFunction("JSTrace", sample.stack[1]);
+ CheckJSFunctionAtAddress("JSFuncDoTrace", sample.stack[0]);
+ CheckJSFunctionAtAddress("JSTrace", sample.stack[1]);
}
@@ -342,19 +328,18 @@
// script [JS]
// OuterJSTrace() [JS]
// JSTrace() [JS]
- // JSFuncDoTrace() [JS] [captures EBP value and encodes it as Smi]
- // js_trace(EBP encoded as Smi) [native (extension)]
+ // JSFuncDoTrace() [JS]
+ // js_trace(EBP) [native (extension)]
// DoTraceHideCEntryFPAddress(EBP) [native]
// StackTracer::Trace
//
// The last JS function called. It is only visible through
// sample.function, as its return address is above captured EBP value.
- CHECK_EQ(GetGlobalJSFunction("JSFuncDoTrace")->address(),
- sample.function);
+ CheckJSFunctionAtAddress("JSFuncDoTrace", sample.function);
CHECK_GT(sample.frames_count, 1);
// Stack sampling will start from the caller of JSFuncDoTrace,
i.e. "JSTrace"
- CheckObjectIsJSFunction("JSTrace", sample.stack[0]);
- CheckObjectIsJSFunction("OuterJSTrace", sample.stack[1]);
+ CheckJSFunctionAtAddress("JSTrace", sample.stack[0]);
+ CheckJSFunctionAtAddress("OuterJSTrace", sample.stack[1]);
}
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev