00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "frames-inl.h"
00031 #include "scopeinfo.h"
00032 #include "string-stream.h"
00033 #include "top.h"
00034 #include "zone-inl.h"
00035
00036 namespace v8 { namespace internal {
00037
00038
00039
00040 class StackHandlerIterator BASE_EMBEDDED {
00041 public:
00042 StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
00043 : limit_(frame->fp()), handler_(handler) {
00044
00045 ASSERT(frame->sp() <= handler->address());
00046 }
00047
00048 StackHandler* handler() const { return handler_; }
00049
00050 bool done() { return handler_->address() > limit_; }
00051 void Advance() {
00052 ASSERT(!done());
00053 handler_ = handler_->next();
00054 }
00055
00056 private:
00057 const Address limit_;
00058 StackHandler* handler_;
00059 };
00060
00061
00062
00063
00064
00065 #define INITIALIZE_SINGLETON(type, field) field##_(this),
00066 StackFrameIterator::StackFrameIterator()
00067 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
00068 frame_(NULL), handler_(NULL), thread_(Top::GetCurrentThread()) {
00069 Reset();
00070 }
00071 StackFrameIterator::StackFrameIterator(ThreadLocalTop* t)
00072 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
00073 frame_(NULL), handler_(NULL), thread_(t) {
00074 Reset();
00075 }
00076 #undef INITIALIZE_SINGLETON
00077
00078
00079 void StackFrameIterator::Advance() {
00080 ASSERT(!done());
00081
00082
00083
00084
00085 StackFrame::State state;
00086 StackFrame::Type type = frame_->GetCallerState(&state);
00087
00088
00089 StackHandlerIterator it(frame_, handler_);
00090 while (!it.done()) it.Advance();
00091 handler_ = it.handler();
00092
00093
00094 frame_ = SingletonFor(type, &state);
00095
00096
00097
00098 ASSERT(!done() || handler_ == NULL);
00099 }
00100
00101
00102 void StackFrameIterator::Reset() {
00103 Address fp = Top::c_entry_fp(thread_);
00104 StackFrame::State state;
00105 StackFrame::Type type = ExitFrame::GetStateForFramePointer(fp, &state);
00106 frame_ = SingletonFor(type, &state);
00107 handler_ = StackHandler::FromAddress(Top::handler(thread_));
00108 }
00109
00110
00111 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
00112 StackFrame::State* state) {
00113 #define FRAME_TYPE_CASE(type, field) \
00114 case StackFrame::type: result = &field##_; break;
00115
00116 StackFrame* result = NULL;
00117 switch (type) {
00118 case StackFrame::NONE: return NULL;
00119 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
00120 default: break;
00121 }
00122 ASSERT(result != NULL);
00123 result->state_ = *state;
00124 return result;
00125
00126 #undef FRAME_TYPE_CASE
00127 }
00128
00129
00130
00131
00132
00133 JavaScriptFrameIterator::JavaScriptFrameIterator(StackFrame::Id id) {
00134 while (true) {
00135 Advance();
00136 if (frame()->id() == id) return;
00137 }
00138 }
00139
00140
00141 void JavaScriptFrameIterator::Advance() {
00142 do {
00143 iterator_.Advance();
00144 } while (!iterator_.done() && !iterator_.frame()->is_java_script());
00145 }
00146
00147
00148 void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
00149 if (!frame()->has_adapted_arguments()) return;
00150 iterator_.Advance();
00151 ASSERT(iterator_.frame()->is_arguments_adaptor());
00152 }
00153
00154
00155 void JavaScriptFrameIterator::Reset() {
00156 iterator_.Reset();
00157 Advance();
00158 }
00159
00160
00161
00162
00163
00164 void StackHandler::Cook(Code* code) {
00165 ASSERT(code->contains(pc()));
00166 set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
00167 }
00168
00169
00170 void StackHandler::Uncook(Code* code) {
00171 set_pc(code->instruction_start() + OffsetFrom(pc()));
00172 ASSERT(code->contains(pc()));
00173 }
00174
00175
00176
00177
00178
00179 bool StackFrame::HasHandler() const {
00180 StackHandlerIterator it(this, top_handler());
00181 return !it.done();
00182 }
00183
00184
00185 void StackFrame::CookFramesForThread(ThreadLocalTop* thread) {
00186 ASSERT(!thread->stack_is_cooked());
00187 for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
00188 it.frame()->Cook();
00189 }
00190 thread->set_stack_is_cooked(true);
00191 }
00192
00193
00194 void StackFrame::UncookFramesForThread(ThreadLocalTop* thread) {
00195 ASSERT(thread->stack_is_cooked());
00196 for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
00197 it.frame()->Uncook();
00198 }
00199 thread->set_stack_is_cooked(false);
00200 }
00201
00202
00203 void StackFrame::Cook() {
00204 Code* code = FindCode();
00205 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
00206 it.handler()->Cook(code);
00207 }
00208 ASSERT(code->contains(pc()));
00209 set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
00210 }
00211
00212
00213 void StackFrame::Uncook() {
00214 Code* code = FindCode();
00215 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
00216 it.handler()->Uncook(code);
00217 }
00218 set_pc(code->instruction_start() + OffsetFrom(pc()));
00219 ASSERT(code->contains(pc()));
00220 }
00221
00222
00223 Code* EntryFrame::FindCode() const {
00224 return Heap::js_entry_code();
00225 }
00226
00227
00228 StackFrame::Type EntryFrame::GetCallerState(State* state) const {
00229 const int offset = EntryFrameConstants::kCallerFPOffset;
00230 Address fp = Memory::Address_at(this->fp() + offset);
00231 return ExitFrame::GetStateForFramePointer(fp, state);
00232 }
00233
00234
00235 Code* EntryConstructFrame::FindCode() const {
00236 return Heap::js_construct_entry_code();
00237 }
00238
00239
00240 Code* ExitFrame::FindCode() const {
00241 return Heap::c_entry_code();
00242 }
00243
00244
00245 StackFrame::Type ExitFrame::GetCallerState(State* state) const {
00246
00247 state->sp = pp();
00248 state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
00249 state->pc_address
00250 = reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset);
00251 return ComputeType(state);
00252 }
00253
00254
00255 Address ExitFrame::GetCallerStackPointer() const {
00256 return fp() + ExitFrameConstants::kPPDisplacement;
00257 }
00258
00259
00260 Code* ExitDebugFrame::FindCode() const {
00261 return Heap::c_entry_debug_break_code();
00262 }
00263
00264
00265 Address StandardFrame::GetExpressionAddress(int n) const {
00266 const int offset = StandardFrameConstants::kExpressionsOffset;
00267 return fp() + offset - n * kPointerSize;
00268 }
00269
00270
00271 int StandardFrame::ComputeExpressionsCount() const {
00272 const int offset =
00273 StandardFrameConstants::kExpressionsOffset + kPointerSize;
00274 Address base = fp() + offset;
00275 Address limit = sp();
00276 ASSERT(base >= limit);
00277
00278 return (base - limit) / kPointerSize;
00279 }
00280
00281
00282 StackFrame::Type StandardFrame::GetCallerState(State* state) const {
00283 state->sp = caller_sp();
00284 state->fp = caller_fp();
00285 state->pc_address = reinterpret_cast<Address*>(ComputePCAddress(fp()));
00286 return ComputeType(state);
00287 }
00288
00289
00290 bool StandardFrame::IsExpressionInsideHandler(int n) const {
00291 Address address = GetExpressionAddress(n);
00292 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
00293 if (it.handler()->includes(address)) return true;
00294 }
00295 return false;
00296 }
00297
00298
00299 Object* JavaScriptFrame::GetParameter(int index) const {
00300 ASSERT(index >= 0 && index < ComputeParametersCount());
00301 const int offset = JavaScriptFrameConstants::kParam0Offset;
00302 return Memory::Object_at(pp() + offset - (index * kPointerSize));
00303 }
00304
00305
00306 int JavaScriptFrame::ComputeParametersCount() const {
00307 Address base = pp() + JavaScriptFrameConstants::kReceiverOffset;
00308 Address limit = fp() + JavaScriptFrameConstants::kSavedRegistersOffset;
00309 return (base - limit) / kPointerSize;
00310 }
00311
00312
00313 bool JavaScriptFrame::IsConstructor() const {
00314 Address fp = caller_fp();
00315 if (has_adapted_arguments()) {
00316
00317 fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
00318 }
00319 return IsConstructFrame(fp);
00320 }
00321
00322
00323 Code* ArgumentsAdaptorFrame::FindCode() const {
00324 return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline);
00325 }
00326
00327
00328 Code* InternalFrame::FindCode() const {
00329 const int offset = InternalFrameConstants::kCodeOffset;
00330 Object* code = Memory::Object_at(fp() + offset);
00331 if (code == NULL) {
00332
00333 code = Heap::FindCodeObject(pc());
00334 ASSERT(!code->IsFailure());
00335 Memory::Object_at(fp() + offset) = code;
00336 }
00337 ASSERT(code != NULL);
00338 return Code::cast(code);
00339 }
00340
00341
00342 void StackFrame::PrintIndex(StringStream* accumulator,
00343 PrintMode mode,
00344 int index) {
00345 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
00346 }
00347
00348
00349 void JavaScriptFrame::Print(StringStream* accumulator,
00350 PrintMode mode,
00351 int index) const {
00352 HandleScope scope;
00353 Object* receiver = this->receiver();
00354 Object* function = this->function();
00355
00356 accumulator->PrintSecurityTokenIfChanged(function);
00357 PrintIndex(accumulator, mode, index);
00358 Code* code = NULL;
00359 if (IsConstructor()) accumulator->Add("new ");
00360 accumulator->PrintFunction(function, receiver, &code);
00361 accumulator->Add("(this=%o", receiver);
00362
00363
00364
00365
00366 ScopeInfo<PreallocatedStorage> info(code);
00367
00368
00369 int parameters_count = ComputeParametersCount();
00370 for (int i = 0; i < parameters_count; i++) {
00371 accumulator->Add(",");
00372
00373
00374
00375 if (i < info.number_of_parameters()) {
00376 accumulator->PrintName(*info.parameter_name(i));
00377 accumulator->Add("=");
00378 }
00379 accumulator->Add("%o", GetParameter(i));
00380 }
00381
00382 accumulator->Add(")");
00383 if (mode == OVERVIEW) {
00384 accumulator->Add("\n");
00385 return;
00386 }
00387 accumulator->Add(" {\n");
00388
00389
00390 int stack_locals_count = info.number_of_stack_slots();
00391 int heap_locals_count = info.number_of_context_slots();
00392 int expressions_count = ComputeExpressionsCount();
00393
00394
00395 if (stack_locals_count > 0) {
00396 accumulator->Add(" // stack-allocated locals\n");
00397 }
00398 for (int i = 0; i < stack_locals_count; i++) {
00399 accumulator->Add(" var ");
00400 accumulator->PrintName(*info.stack_slot_name(i));
00401 accumulator->Add(" = ");
00402 if (i < expressions_count) {
00403 accumulator->Add("%o", GetExpression(i));
00404 } else {
00405 accumulator->Add("// no expression found - inconsistent frame?");
00406 }
00407 accumulator->Add("\n");
00408 }
00409
00410
00411 Context* context = NULL;
00412 if (this->context() != NULL && this->context()->IsContext()) {
00413 context = Context::cast(this->context());
00414 }
00415
00416
00417 if (heap_locals_count > Context::MIN_CONTEXT_SLOTS) {
00418 accumulator->Add(" // heap-allocated locals\n");
00419 }
00420 for (int i = Context::MIN_CONTEXT_SLOTS; i < heap_locals_count; i++) {
00421 accumulator->Add(" var ");
00422 accumulator->PrintName(*info.context_slot_name(i));
00423 accumulator->Add(" = ");
00424 if (context != NULL) {
00425 if (i < context->length()) {
00426 accumulator->Add("%o", context->get(i));
00427 } else {
00428 accumulator->Add(
00429 "// warning: missing context slot - inconsistent frame?");
00430 }
00431 } else {
00432 accumulator->Add("// warning: no context found - inconsistent frame?");
00433 }
00434 accumulator->Add("\n");
00435 }
00436
00437
00438 int expressions_start = stack_locals_count;
00439 if (expressions_start < expressions_count) {
00440 accumulator->Add(" // expression stack (top to bottom)\n");
00441 }
00442 for (int i = expressions_count - 1; i >= expressions_start; i--) {
00443 if (IsExpressionInsideHandler(i)) continue;
00444 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
00445 }
00446
00447
00448 if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
00449 SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
00450 accumulator->Add("--------- s o u r c e c o d e ---------\n");
00451 shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
00452 accumulator->Add("\n-----------------------------------------\n");
00453 }
00454
00455 accumulator->Add("}\n\n");
00456 }
00457
00458
00459 void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
00460 PrintMode mode,
00461 int index) const {
00462 int actual = ComputeParametersCount();
00463 int expected = -1;
00464 Object* function = this->function();
00465 if (function->IsJSFunction()) {
00466 expected = JSFunction::cast(function)->shared()->formal_parameter_count();
00467 }
00468
00469 PrintIndex(accumulator, mode, index);
00470 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
00471 if (mode == OVERVIEW) {
00472 accumulator->Add("\n");
00473 return;
00474 }
00475 accumulator->Add(" {\n");
00476
00477
00478 if (actual > 0) accumulator->Add(" // actual arguments\n");
00479 for (int i = 0; i < actual; i++) {
00480 accumulator->Add(" [%02d] : %o", i, GetParameter(i));
00481 if (expected != -1 && i >= expected) {
00482 accumulator->Add(" // not passed to callee");
00483 }
00484 accumulator->Add("\n");
00485 }
00486
00487 accumulator->Add("}\n\n");
00488 }
00489
00490
00491 void EntryFrame::Iterate(ObjectVisitor* v) const {
00492 StackHandlerIterator it(this, top_handler());
00493 ASSERT(!it.done());
00494 StackHandler* handler = it.handler();
00495 ASSERT(handler->is_entry());
00496 handler->Iterate(v);
00497
00498
00499 if (kDebug) {
00500 it.Advance();
00501 ASSERT(it.done());
00502 }
00503 }
00504
00505
00506 void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
00507 const int offset = StandardFrameConstants::kContextOffset;
00508 Object** base = &Memory::Object_at(sp());
00509 Object** limit = &Memory::Object_at(fp() + offset) + 1;
00510 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
00511 StackHandler* handler = it.handler();
00512
00513
00514
00515 const Address address = handler->address();
00516 v->VisitPointers(base, reinterpret_cast<Object**>(address));
00517 base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
00518
00519 handler->Iterate(v);
00520 }
00521 v->VisitPointers(base, limit);
00522 }
00523
00524
00525 void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
00526 IterateExpressions(v);
00527
00528
00529 const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset;
00530 const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset;
00531 Object** base = &Memory::Object_at(fp() + kBaseOffset);
00532 Object** limit = &Memory::Object_at(pp() + kLimitOffset) + 1;
00533 v->VisitPointers(base, limit);
00534 }
00535
00536
00537 void InternalFrame::Iterate(ObjectVisitor* v) const {
00538
00539
00540 IterateExpressions(v);
00541 }
00542
00543
00544
00545
00546
00547 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
00548 ASSERT(n >= 0);
00549 for (int i = 0; i <= n; i++) {
00550 while (!iterator_.frame()->is_java_script()) iterator_.Advance();
00551 if (i == n) return JavaScriptFrame::cast(iterator_.frame());
00552 iterator_.Advance();
00553 }
00554 UNREACHABLE();
00555 return NULL;
00556 }
00557
00558
00559
00560
00561
00562 int NumRegs(RegList reglist) {
00563 int n = 0;
00564 while (reglist != 0) {
00565 n++;
00566 reglist &= reglist - 1;
00567 }
00568 return n;
00569 }
00570
00571
00572 int JSCallerSavedCode(int n) {
00573 static int reg_code[kNumJSCallerSaved];
00574 static bool initialized = false;
00575 if (!initialized) {
00576 initialized = true;
00577 int i = 0;
00578 for (int r = 0; r < kNumRegs; r++)
00579 if ((kJSCallerSaved & (1 << r)) != 0)
00580 reg_code[i++] = r;
00581
00582 ASSERT(i == kNumJSCallerSaved);
00583 }
00584 ASSERT(0 <= n && n < kNumJSCallerSaved);
00585 return reg_code[n];
00586 }
00587
00588
00589 } }