OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/ast.h" | 7 #include "src/ast.h" |
8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
9 #include "src/frames-inl.h" | 9 #include "src/frames-inl.h" |
10 #include "src/full-codegen.h" | 10 #include "src/full-codegen.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 StackFrame::return_address_location_resolver_ = NULL; | 22 StackFrame::return_address_location_resolver_ = NULL; |
23 | 23 |
24 | 24 |
25 // Iterator that supports traversing the stack handlers of a | 25 // Iterator that supports traversing the stack handlers of a |
26 // particular frame. Needs to know the top of the handler chain. | 26 // particular frame. Needs to know the top of the handler chain. |
27 class StackHandlerIterator BASE_EMBEDDED { | 27 class StackHandlerIterator BASE_EMBEDDED { |
28 public: | 28 public: |
29 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) | 29 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) |
30 : limit_(frame->fp()), handler_(handler) { | 30 : limit_(frame->fp()), handler_(handler) { |
31 // Make sure the handler has already been unwound to this frame. | 31 // Make sure the handler has already been unwound to this frame. |
32 ASSERT(frame->sp() <= handler->address()); | 32 DCHECK(frame->sp() <= handler->address()); |
33 } | 33 } |
34 | 34 |
35 StackHandler* handler() const { return handler_; } | 35 StackHandler* handler() const { return handler_; } |
36 | 36 |
37 bool done() { | 37 bool done() { |
38 return handler_ == NULL || handler_->address() > limit_; | 38 return handler_ == NULL || handler_->address() > limit_; |
39 } | 39 } |
40 void Advance() { | 40 void Advance() { |
41 ASSERT(!done()); | 41 DCHECK(!done()); |
42 handler_ = handler_->next(); | 42 handler_ = handler_->next(); |
43 } | 43 } |
44 | 44 |
45 private: | 45 private: |
46 const Address limit_; | 46 const Address limit_; |
47 StackHandler* handler_; | 47 StackHandler* handler_; |
48 }; | 48 }; |
49 | 49 |
50 | 50 |
51 // ------------------------------------------------------------------------- | 51 // ------------------------------------------------------------------------- |
(...skipping 16 matching lines...) Expand all Loading... |
68 } | 68 } |
69 | 69 |
70 | 70 |
71 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) | 71 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) |
72 : StackFrameIteratorBase(isolate, true) { | 72 : StackFrameIteratorBase(isolate, true) { |
73 Reset(t); | 73 Reset(t); |
74 } | 74 } |
75 | 75 |
76 | 76 |
77 void StackFrameIterator::Advance() { | 77 void StackFrameIterator::Advance() { |
78 ASSERT(!done()); | 78 DCHECK(!done()); |
79 // Compute the state of the calling frame before restoring | 79 // Compute the state of the calling frame before restoring |
80 // callee-saved registers and unwinding handlers. This allows the | 80 // callee-saved registers and unwinding handlers. This allows the |
81 // frame code that computes the caller state to access the top | 81 // frame code that computes the caller state to access the top |
82 // handler and the value of any callee-saved register if needed. | 82 // handler and the value of any callee-saved register if needed. |
83 StackFrame::State state; | 83 StackFrame::State state; |
84 StackFrame::Type type = frame_->GetCallerState(&state); | 84 StackFrame::Type type = frame_->GetCallerState(&state); |
85 | 85 |
86 // Unwind handlers corresponding to the current frame. | 86 // Unwind handlers corresponding to the current frame. |
87 StackHandlerIterator it(frame_, handler_); | 87 StackHandlerIterator it(frame_, handler_); |
88 while (!it.done()) it.Advance(); | 88 while (!it.done()) it.Advance(); |
89 handler_ = it.handler(); | 89 handler_ = it.handler(); |
90 | 90 |
91 // Advance to the calling frame. | 91 // Advance to the calling frame. |
92 frame_ = SingletonFor(type, &state); | 92 frame_ = SingletonFor(type, &state); |
93 | 93 |
94 // When we're done iterating over the stack frames, the handler | 94 // When we're done iterating over the stack frames, the handler |
95 // chain must have been completely unwound. | 95 // chain must have been completely unwound. |
96 ASSERT(!done() || handler_ == NULL); | 96 DCHECK(!done() || handler_ == NULL); |
97 } | 97 } |
98 | 98 |
99 | 99 |
100 void StackFrameIterator::Reset(ThreadLocalTop* top) { | 100 void StackFrameIterator::Reset(ThreadLocalTop* top) { |
101 StackFrame::State state; | 101 StackFrame::State state; |
102 StackFrame::Type type = ExitFrame::GetStateForFramePointer( | 102 StackFrame::Type type = ExitFrame::GetStateForFramePointer( |
103 Isolate::c_entry_fp(top), &state); | 103 Isolate::c_entry_fp(top), &state); |
104 handler_ = StackHandler::FromAddress(Isolate::handler(top)); | 104 handler_ = StackHandler::FromAddress(Isolate::handler(top)); |
105 if (SingletonFor(type) == NULL) return; | 105 if (SingletonFor(type) == NULL) return; |
106 frame_ = SingletonFor(type, &state); | 106 frame_ = SingletonFor(type, &state); |
107 } | 107 } |
108 | 108 |
109 | 109 |
110 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type, | 110 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type, |
111 StackFrame::State* state) { | 111 StackFrame::State* state) { |
112 if (type == StackFrame::NONE) return NULL; | 112 if (type == StackFrame::NONE) return NULL; |
113 StackFrame* result = SingletonFor(type); | 113 StackFrame* result = SingletonFor(type); |
114 ASSERT(result != NULL); | 114 DCHECK(result != NULL); |
115 result->state_ = *state; | 115 result->state_ = *state; |
116 return result; | 116 return result; |
117 } | 117 } |
118 | 118 |
119 | 119 |
120 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) { | 120 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) { |
121 #define FRAME_TYPE_CASE(type, field) \ | 121 #define FRAME_TYPE_CASE(type, field) \ |
122 case StackFrame::type: result = &field##_; break; | 122 case StackFrame::type: result = &field##_; break; |
123 | 123 |
124 StackFrame* result = NULL; | 124 StackFrame* result = NULL; |
(...skipping 24 matching lines...) Expand all Loading... |
149 void JavaScriptFrameIterator::Advance() { | 149 void JavaScriptFrameIterator::Advance() { |
150 do { | 150 do { |
151 iterator_.Advance(); | 151 iterator_.Advance(); |
152 } while (!iterator_.done() && !iterator_.frame()->is_java_script()); | 152 } while (!iterator_.done() && !iterator_.frame()->is_java_script()); |
153 } | 153 } |
154 | 154 |
155 | 155 |
156 void JavaScriptFrameIterator::AdvanceToArgumentsFrame() { | 156 void JavaScriptFrameIterator::AdvanceToArgumentsFrame() { |
157 if (!frame()->has_adapted_arguments()) return; | 157 if (!frame()->has_adapted_arguments()) return; |
158 iterator_.Advance(); | 158 iterator_.Advance(); |
159 ASSERT(iterator_.frame()->is_arguments_adaptor()); | 159 DCHECK(iterator_.frame()->is_arguments_adaptor()); |
160 } | 160 } |
161 | 161 |
162 | 162 |
163 // ------------------------------------------------------------------------- | 163 // ------------------------------------------------------------------------- |
164 | 164 |
165 | 165 |
166 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) | 166 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) |
167 : JavaScriptFrameIterator(isolate) { | 167 : JavaScriptFrameIterator(isolate) { |
168 if (!done() && !IsValidFrame()) Advance(); | 168 if (!done() && !IsValidFrame()) Advance(); |
169 } | 169 } |
(...skipping 28 matching lines...) Expand all Loading... |
198 high_bound_(js_entry_sp), | 198 high_bound_(js_entry_sp), |
199 top_frame_type_(StackFrame::NONE), | 199 top_frame_type_(StackFrame::NONE), |
200 external_callback_scope_(isolate->external_callback_scope()) { | 200 external_callback_scope_(isolate->external_callback_scope()) { |
201 StackFrame::State state; | 201 StackFrame::State state; |
202 StackFrame::Type type; | 202 StackFrame::Type type; |
203 ThreadLocalTop* top = isolate->thread_local_top(); | 203 ThreadLocalTop* top = isolate->thread_local_top(); |
204 if (IsValidTop(top)) { | 204 if (IsValidTop(top)) { |
205 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); | 205 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); |
206 top_frame_type_ = type; | 206 top_frame_type_ = type; |
207 } else if (IsValidStackAddress(fp)) { | 207 } else if (IsValidStackAddress(fp)) { |
208 ASSERT(fp != NULL); | 208 DCHECK(fp != NULL); |
209 state.fp = fp; | 209 state.fp = fp; |
210 state.sp = sp; | 210 state.sp = sp; |
211 state.pc_address = StackFrame::ResolveReturnAddressLocation( | 211 state.pc_address = StackFrame::ResolveReturnAddressLocation( |
212 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); | 212 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); |
213 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, | 213 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, |
214 // we check only that kMarkerOffset is within the stack bounds and do | 214 // we check only that kMarkerOffset is within the stack bounds and do |
215 // compile time check that kContextOffset slot is pushed on the stack before | 215 // compile time check that kContextOffset slot is pushed on the stack before |
216 // kMarkerOffset. | 216 // kMarkerOffset. |
217 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset < | 217 STATIC_ASSERT(StandardFrameConstants::kMarkerOffset < |
218 StandardFrameConstants::kContextOffset); | 218 StandardFrameConstants::kContextOffset); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 if (!IsValidExitFrame(c_entry_fp)) return false; | 251 if (!IsValidExitFrame(c_entry_fp)) return false; |
252 // There should be at least one JS_ENTRY stack handler. | 252 // There should be at least one JS_ENTRY stack handler. |
253 Address handler = Isolate::handler(top); | 253 Address handler = Isolate::handler(top); |
254 if (handler == NULL) return false; | 254 if (handler == NULL) return false; |
255 // Check that there are no js frames on top of the native frames. | 255 // Check that there are no js frames on top of the native frames. |
256 return c_entry_fp < handler; | 256 return c_entry_fp < handler; |
257 } | 257 } |
258 | 258 |
259 | 259 |
260 void SafeStackFrameIterator::AdvanceOneFrame() { | 260 void SafeStackFrameIterator::AdvanceOneFrame() { |
261 ASSERT(!done()); | 261 DCHECK(!done()); |
262 StackFrame* last_frame = frame_; | 262 StackFrame* last_frame = frame_; |
263 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); | 263 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); |
264 // Before advancing to the next stack frame, perform pointer validity tests. | 264 // Before advancing to the next stack frame, perform pointer validity tests. |
265 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) { | 265 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) { |
266 frame_ = NULL; | 266 frame_ = NULL; |
267 return; | 267 return; |
268 } | 268 } |
269 | 269 |
270 // Advance to the previous frame. | 270 // Advance to the previous frame. |
271 StackFrame::State state; | 271 StackFrame::State state; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 // frame beneath it. There may be other EXIT frames on top of the | 334 // frame beneath it. There may be other EXIT frames on top of the |
335 // ExternalCallbackScope, just skip them as we cannot collect any useful | 335 // ExternalCallbackScope, just skip them as we cannot collect any useful |
336 // information about them. | 336 // information about them. |
337 if (external_callback_scope_->scope_address() < frame_->fp()) { | 337 if (external_callback_scope_->scope_address() < frame_->fp()) { |
338 Address* callback_address = | 338 Address* callback_address = |
339 external_callback_scope_->callback_address(); | 339 external_callback_scope_->callback_address(); |
340 if (*callback_address != NULL) { | 340 if (*callback_address != NULL) { |
341 frame_->state_.pc_address = callback_address; | 341 frame_->state_.pc_address = callback_address; |
342 } | 342 } |
343 external_callback_scope_ = external_callback_scope_->previous(); | 343 external_callback_scope_ = external_callback_scope_->previous(); |
344 ASSERT(external_callback_scope_ == NULL || | 344 DCHECK(external_callback_scope_ == NULL || |
345 external_callback_scope_->scope_address() > frame_->fp()); | 345 external_callback_scope_->scope_address() > frame_->fp()); |
346 return; | 346 return; |
347 } | 347 } |
348 } | 348 } |
349 } | 349 } |
350 } | 350 } |
351 | 351 |
352 | 352 |
353 // ------------------------------------------------------------------------- | 353 // ------------------------------------------------------------------------- |
354 | 354 |
355 | 355 |
356 Code* StackFrame::GetSafepointData(Isolate* isolate, | 356 Code* StackFrame::GetSafepointData(Isolate* isolate, |
357 Address inner_pointer, | 357 Address inner_pointer, |
358 SafepointEntry* safepoint_entry, | 358 SafepointEntry* safepoint_entry, |
359 unsigned* stack_slots) { | 359 unsigned* stack_slots) { |
360 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = | 360 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = |
361 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); | 361 isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); |
362 if (!entry->safepoint_entry.is_valid()) { | 362 if (!entry->safepoint_entry.is_valid()) { |
363 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer); | 363 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer); |
364 ASSERT(entry->safepoint_entry.is_valid()); | 364 DCHECK(entry->safepoint_entry.is_valid()); |
365 } else { | 365 } else { |
366 ASSERT(entry->safepoint_entry.Equals( | 366 DCHECK(entry->safepoint_entry.Equals( |
367 entry->code->GetSafepointEntry(inner_pointer))); | 367 entry->code->GetSafepointEntry(inner_pointer))); |
368 } | 368 } |
369 | 369 |
370 // Fill in the results and return the code. | 370 // Fill in the results and return the code. |
371 Code* code = entry->code; | 371 Code* code = entry->code; |
372 *safepoint_entry = entry->safepoint_entry; | 372 *safepoint_entry = entry->safepoint_entry; |
373 *stack_slots = code->stack_slots(); | 373 *stack_slots = code->stack_slots(); |
374 return code; | 374 return code; |
375 } | 375 } |
376 | 376 |
377 | 377 |
378 bool StackFrame::HasHandler() const { | 378 bool StackFrame::HasHandler() const { |
379 StackHandlerIterator it(this, top_handler()); | 379 StackHandlerIterator it(this, top_handler()); |
380 return !it.done(); | 380 return !it.done(); |
381 } | 381 } |
382 | 382 |
383 | 383 |
384 #ifdef DEBUG | 384 #ifdef DEBUG |
385 static bool GcSafeCodeContains(HeapObject* object, Address addr); | 385 static bool GcSafeCodeContains(HeapObject* object, Address addr); |
386 #endif | 386 #endif |
387 | 387 |
388 | 388 |
389 void StackFrame::IteratePc(ObjectVisitor* v, | 389 void StackFrame::IteratePc(ObjectVisitor* v, |
390 Address* pc_address, | 390 Address* pc_address, |
391 Code* holder) { | 391 Code* holder) { |
392 Address pc = *pc_address; | 392 Address pc = *pc_address; |
393 ASSERT(GcSafeCodeContains(holder, pc)); | 393 DCHECK(GcSafeCodeContains(holder, pc)); |
394 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start()); | 394 unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start()); |
395 Object* code = holder; | 395 Object* code = holder; |
396 v->VisitPointer(&code); | 396 v->VisitPointer(&code); |
397 if (code != holder) { | 397 if (code != holder) { |
398 holder = reinterpret_cast<Code*>(code); | 398 holder = reinterpret_cast<Code*>(code); |
399 pc = holder->instruction_start() + pc_offset; | 399 pc = holder->instruction_start() + pc_offset; |
400 *pc_address = pc; | 400 *pc_address = pc; |
401 } | 401 } |
402 } | 402 } |
403 | 403 |
404 | 404 |
405 void StackFrame::SetReturnAddressLocationResolver( | 405 void StackFrame::SetReturnAddressLocationResolver( |
406 ReturnAddressLocationResolver resolver) { | 406 ReturnAddressLocationResolver resolver) { |
407 ASSERT(return_address_location_resolver_ == NULL); | 407 DCHECK(return_address_location_resolver_ == NULL); |
408 return_address_location_resolver_ = resolver; | 408 return_address_location_resolver_ = resolver; |
409 } | 409 } |
410 | 410 |
411 | 411 |
412 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, | 412 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, |
413 State* state) { | 413 State* state) { |
414 ASSERT(state->fp != NULL); | 414 DCHECK(state->fp != NULL); |
415 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { | 415 if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) { |
416 return ARGUMENTS_ADAPTOR; | 416 return ARGUMENTS_ADAPTOR; |
417 } | 417 } |
418 // The marker and function offsets overlap. If the marker isn't a | 418 // The marker and function offsets overlap. If the marker isn't a |
419 // smi then the frame is a JavaScript frame -- and the marker is | 419 // smi then the frame is a JavaScript frame -- and the marker is |
420 // really the function. | 420 // really the function. |
421 const int offset = StandardFrameConstants::kMarkerOffset; | 421 const int offset = StandardFrameConstants::kMarkerOffset; |
422 Object* marker = Memory::Object_at(state->fp + offset); | 422 Object* marker = Memory::Object_at(state->fp + offset); |
423 if (!marker->IsSmi()) { | 423 if (!marker->IsSmi()) { |
424 // If we're using a "safe" stack iterator, we treat optimized | 424 // If we're using a "safe" stack iterator, we treat optimized |
425 // frames as normal JavaScript frames to avoid having to look | 425 // frames as normal JavaScript frames to avoid having to look |
426 // into the heap to determine the state. This is safe as long | 426 // into the heap to determine the state. This is safe as long |
427 // as nobody tries to GC... | 427 // as nobody tries to GC... |
428 if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT; | 428 if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT; |
429 Code::Kind kind = GetContainingCode(iterator->isolate(), | 429 Code::Kind kind = GetContainingCode(iterator->isolate(), |
430 *(state->pc_address))->kind(); | 430 *(state->pc_address))->kind(); |
431 ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); | 431 DCHECK(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION); |
432 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; | 432 return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT; |
433 } | 433 } |
434 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); | 434 return static_cast<StackFrame::Type>(Smi::cast(marker)->value()); |
435 } | 435 } |
436 | 436 |
437 | 437 |
438 #ifdef DEBUG | 438 #ifdef DEBUG |
439 bool StackFrame::can_access_heap_objects() const { | 439 bool StackFrame::can_access_heap_objects() const { |
440 return iterator_->can_access_heap_objects_; | 440 return iterator_->can_access_heap_objects_; |
441 } | 441 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 | 532 |
533 Address ExitFrame::GetCallerStackPointer() const { | 533 Address ExitFrame::GetCallerStackPointer() const { |
534 return fp() + ExitFrameConstants::kCallerSPDisplacement; | 534 return fp() + ExitFrameConstants::kCallerSPDisplacement; |
535 } | 535 } |
536 | 536 |
537 | 537 |
538 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { | 538 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { |
539 if (fp == 0) return NONE; | 539 if (fp == 0) return NONE; |
540 Address sp = ComputeStackPointer(fp); | 540 Address sp = ComputeStackPointer(fp); |
541 FillState(fp, sp, state); | 541 FillState(fp, sp, state); |
542 ASSERT(*state->pc_address != NULL); | 542 DCHECK(*state->pc_address != NULL); |
543 return EXIT; | 543 return EXIT; |
544 } | 544 } |
545 | 545 |
546 | 546 |
547 Address ExitFrame::ComputeStackPointer(Address fp) { | 547 Address ExitFrame::ComputeStackPointer(Address fp) { |
548 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); | 548 return Memory::Address_at(fp + ExitFrameConstants::kSPOffset); |
549 } | 549 } |
550 | 550 |
551 | 551 |
552 void ExitFrame::FillState(Address fp, Address sp, State* state) { | 552 void ExitFrame::FillState(Address fp, Address sp, State* state) { |
(...skipping 21 matching lines...) Expand all Loading... |
574 const int offset = StandardFrameConstants::kExpressionsOffset; | 574 const int offset = StandardFrameConstants::kExpressionsOffset; |
575 return fp + offset - n * kPointerSize; | 575 return fp + offset - n * kPointerSize; |
576 } | 576 } |
577 | 577 |
578 | 578 |
579 int StandardFrame::ComputeExpressionsCount() const { | 579 int StandardFrame::ComputeExpressionsCount() const { |
580 const int offset = | 580 const int offset = |
581 StandardFrameConstants::kExpressionsOffset + kPointerSize; | 581 StandardFrameConstants::kExpressionsOffset + kPointerSize; |
582 Address base = fp() + offset; | 582 Address base = fp() + offset; |
583 Address limit = sp(); | 583 Address limit = sp(); |
584 ASSERT(base >= limit); // stack grows downwards | 584 DCHECK(base >= limit); // stack grows downwards |
585 // Include register-allocated locals in number of expressions. | 585 // Include register-allocated locals in number of expressions. |
586 return static_cast<int>((base - limit) / kPointerSize); | 586 return static_cast<int>((base - limit) / kPointerSize); |
587 } | 587 } |
588 | 588 |
589 | 589 |
590 void StandardFrame::ComputeCallerState(State* state) const { | 590 void StandardFrame::ComputeCallerState(State* state) const { |
591 state->sp = caller_sp(); | 591 state->sp = caller_sp(); |
592 state->fp = caller_fp(); | 592 state->fp = caller_fp(); |
593 state->pc_address = ResolveReturnAddressLocation( | 593 state->pc_address = ResolveReturnAddressLocation( |
594 reinterpret_cast<Address*>(ComputePCAddress(fp()))); | 594 reinterpret_cast<Address*>(ComputePCAddress(fp()))); |
(...skipping 13 matching lines...) Expand all Loading... |
608 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 608 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
609 if (it.handler()->includes(address)) return true; | 609 if (it.handler()->includes(address)) return true; |
610 } | 610 } |
611 return false; | 611 return false; |
612 } | 612 } |
613 | 613 |
614 | 614 |
615 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { | 615 void StandardFrame::IterateCompiledFrame(ObjectVisitor* v) const { |
616 // Make sure that we're not doing "safe" stack frame iteration. We cannot | 616 // Make sure that we're not doing "safe" stack frame iteration. We cannot |
617 // possibly find pointers in optimized frames in that state. | 617 // possibly find pointers in optimized frames in that state. |
618 ASSERT(can_access_heap_objects()); | 618 DCHECK(can_access_heap_objects()); |
619 | 619 |
620 // Compute the safepoint information. | 620 // Compute the safepoint information. |
621 unsigned stack_slots = 0; | 621 unsigned stack_slots = 0; |
622 SafepointEntry safepoint_entry; | 622 SafepointEntry safepoint_entry; |
623 Code* code = StackFrame::GetSafepointData( | 623 Code* code = StackFrame::GetSafepointData( |
624 isolate(), pc(), &safepoint_entry, &stack_slots); | 624 isolate(), pc(), &safepoint_entry, &stack_slots); |
625 unsigned slot_space = stack_slots * kPointerSize; | 625 unsigned slot_space = stack_slots * kPointerSize; |
626 | 626 |
627 // Visit the outgoing parameters. | 627 // Visit the outgoing parameters. |
628 Object** parameters_base = &Memory::Object_at(sp()); | 628 Object** parameters_base = &Memory::Object_at(sp()); |
629 Object** parameters_limit = &Memory::Object_at( | 629 Object** parameters_limit = &Memory::Object_at( |
630 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space); | 630 fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space); |
631 | 631 |
632 // Visit the parameters that may be on top of the saved registers. | 632 // Visit the parameters that may be on top of the saved registers. |
633 if (safepoint_entry.argument_count() > 0) { | 633 if (safepoint_entry.argument_count() > 0) { |
634 v->VisitPointers(parameters_base, | 634 v->VisitPointers(parameters_base, |
635 parameters_base + safepoint_entry.argument_count()); | 635 parameters_base + safepoint_entry.argument_count()); |
636 parameters_base += safepoint_entry.argument_count(); | 636 parameters_base += safepoint_entry.argument_count(); |
637 } | 637 } |
638 | 638 |
639 // Skip saved double registers. | 639 // Skip saved double registers. |
640 if (safepoint_entry.has_doubles()) { | 640 if (safepoint_entry.has_doubles()) { |
641 // Number of doubles not known at snapshot time. | 641 // Number of doubles not known at snapshot time. |
642 ASSERT(!isolate()->serializer_enabled()); | 642 DCHECK(!isolate()->serializer_enabled()); |
643 parameters_base += DoubleRegister::NumAllocatableRegisters() * | 643 parameters_base += DoubleRegister::NumAllocatableRegisters() * |
644 kDoubleSize / kPointerSize; | 644 kDoubleSize / kPointerSize; |
645 } | 645 } |
646 | 646 |
647 // Visit the registers that contain pointers if any. | 647 // Visit the registers that contain pointers if any. |
648 if (safepoint_entry.HasRegisters()) { | 648 if (safepoint_entry.HasRegisters()) { |
649 for (int i = kNumSafepointRegisters - 1; i >=0; i--) { | 649 for (int i = kNumSafepointRegisters - 1; i >=0; i--) { |
650 if (safepoint_entry.HasRegisterAt(i)) { | 650 if (safepoint_entry.HasRegisterAt(i)) { |
651 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i); | 651 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i); |
652 v->VisitPointer(parameters_base + reg_stack_index); | 652 v->VisitPointer(parameters_base + reg_stack_index); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 | 701 |
702 int StubFrame::GetNumberOfIncomingArguments() const { | 702 int StubFrame::GetNumberOfIncomingArguments() const { |
703 return 0; | 703 return 0; |
704 } | 704 } |
705 | 705 |
706 | 706 |
707 void OptimizedFrame::Iterate(ObjectVisitor* v) const { | 707 void OptimizedFrame::Iterate(ObjectVisitor* v) const { |
708 #ifdef DEBUG | 708 #ifdef DEBUG |
709 // Make sure that optimized frames do not contain any stack handlers. | 709 // Make sure that optimized frames do not contain any stack handlers. |
710 StackHandlerIterator it(this, top_handler()); | 710 StackHandlerIterator it(this, top_handler()); |
711 ASSERT(it.done()); | 711 DCHECK(it.done()); |
712 #endif | 712 #endif |
713 | 713 |
714 IterateCompiledFrame(v); | 714 IterateCompiledFrame(v); |
715 } | 715 } |
716 | 716 |
717 | 717 |
718 void JavaScriptFrame::SetParameterValue(int index, Object* value) const { | 718 void JavaScriptFrame::SetParameterValue(int index, Object* value) const { |
719 Memory::Object_at(GetParameterSlot(index)) = value; | 719 Memory::Object_at(GetParameterSlot(index)) = value; |
720 } | 720 } |
721 | 721 |
(...skipping 17 matching lines...) Expand all Loading... |
739 } | 739 } |
740 } | 740 } |
741 | 741 |
742 | 742 |
743 Code* JavaScriptFrame::unchecked_code() const { | 743 Code* JavaScriptFrame::unchecked_code() const { |
744 return function()->code(); | 744 return function()->code(); |
745 } | 745 } |
746 | 746 |
747 | 747 |
748 int JavaScriptFrame::GetNumberOfIncomingArguments() const { | 748 int JavaScriptFrame::GetNumberOfIncomingArguments() const { |
749 ASSERT(can_access_heap_objects() && | 749 DCHECK(can_access_heap_objects() && |
750 isolate()->heap()->gc_state() == Heap::NOT_IN_GC); | 750 isolate()->heap()->gc_state() == Heap::NOT_IN_GC); |
751 | 751 |
752 return function()->shared()->formal_parameter_count(); | 752 return function()->shared()->formal_parameter_count(); |
753 } | 753 } |
754 | 754 |
755 | 755 |
756 Address JavaScriptFrame::GetCallerStackPointer() const { | 756 Address JavaScriptFrame::GetCallerStackPointer() const { |
757 return fp() + StandardFrameConstants::kCallerSPOffset; | 757 return fp() + StandardFrameConstants::kCallerSPOffset; |
758 } | 758 } |
759 | 759 |
760 | 760 |
761 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) { | 761 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) { |
762 ASSERT(functions->length() == 0); | 762 DCHECK(functions->length() == 0); |
763 functions->Add(function()); | 763 functions->Add(function()); |
764 } | 764 } |
765 | 765 |
766 | 766 |
767 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { | 767 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) { |
768 ASSERT(functions->length() == 0); | 768 DCHECK(functions->length() == 0); |
769 Code* code_pointer = LookupCode(); | 769 Code* code_pointer = LookupCode(); |
770 int offset = static_cast<int>(pc() - code_pointer->address()); | 770 int offset = static_cast<int>(pc() - code_pointer->address()); |
771 FrameSummary summary(receiver(), | 771 FrameSummary summary(receiver(), |
772 function(), | 772 function(), |
773 code_pointer, | 773 code_pointer, |
774 offset, | 774 offset, |
775 IsConstructor()); | 775 IsConstructor()); |
776 functions->Add(summary); | 776 functions->Add(summary); |
777 } | 777 } |
778 | 778 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 break; | 834 break; |
835 } | 835 } |
836 it.Advance(); | 836 it.Advance(); |
837 } | 837 } |
838 } | 838 } |
839 | 839 |
840 | 840 |
841 void JavaScriptFrame::SaveOperandStack(FixedArray* store, | 841 void JavaScriptFrame::SaveOperandStack(FixedArray* store, |
842 int* stack_handler_index) const { | 842 int* stack_handler_index) const { |
843 int operands_count = store->length(); | 843 int operands_count = store->length(); |
844 ASSERT_LE(operands_count, ComputeOperandsCount()); | 844 DCHECK_LE(operands_count, ComputeOperandsCount()); |
845 | 845 |
846 // Visit the stack in LIFO order, saving operands and stack handlers into the | 846 // Visit the stack in LIFO order, saving operands and stack handlers into the |
847 // array. The saved stack handlers store a link to the next stack handler, | 847 // array. The saved stack handlers store a link to the next stack handler, |
848 // which will allow RestoreOperandStack to rewind the handlers. | 848 // which will allow RestoreOperandStack to rewind the handlers. |
849 StackHandlerIterator it(this, top_handler()); | 849 StackHandlerIterator it(this, top_handler()); |
850 int i = operands_count - 1; | 850 int i = operands_count - 1; |
851 *stack_handler_index = -1; | 851 *stack_handler_index = -1; |
852 for (; !it.done(); it.Advance()) { | 852 for (; !it.done(); it.Advance()) { |
853 StackHandler* handler = it.handler(); | 853 StackHandler* handler = it.handler(); |
854 // Save operands pushed after the handler was pushed. | 854 // Save operands pushed after the handler was pushed. |
855 for (; GetOperandSlot(i) < handler->address(); i--) { | 855 for (; GetOperandSlot(i) < handler->address(); i--) { |
856 store->set(i, GetOperand(i)); | 856 store->set(i, GetOperand(i)); |
857 } | 857 } |
858 ASSERT_GE(i + 1, StackHandlerConstants::kSlotCount); | 858 DCHECK_GE(i + 1, StackHandlerConstants::kSlotCount); |
859 ASSERT_EQ(handler->address(), GetOperandSlot(i)); | 859 DCHECK_EQ(handler->address(), GetOperandSlot(i)); |
860 int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount; | 860 int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount; |
861 handler->Unwind(isolate(), store, next_stack_handler_index, | 861 handler->Unwind(isolate(), store, next_stack_handler_index, |
862 *stack_handler_index); | 862 *stack_handler_index); |
863 *stack_handler_index = next_stack_handler_index; | 863 *stack_handler_index = next_stack_handler_index; |
864 i -= StackHandlerConstants::kSlotCount; | 864 i -= StackHandlerConstants::kSlotCount; |
865 } | 865 } |
866 | 866 |
867 // Save any remaining operands. | 867 // Save any remaining operands. |
868 for (; i >= 0; i--) { | 868 for (; i >= 0; i--) { |
869 store->set(i, GetOperand(i)); | 869 store->set(i, GetOperand(i)); |
870 } | 870 } |
871 } | 871 } |
872 | 872 |
873 | 873 |
874 void JavaScriptFrame::RestoreOperandStack(FixedArray* store, | 874 void JavaScriptFrame::RestoreOperandStack(FixedArray* store, |
875 int stack_handler_index) { | 875 int stack_handler_index) { |
876 int operands_count = store->length(); | 876 int operands_count = store->length(); |
877 ASSERT_LE(operands_count, ComputeOperandsCount()); | 877 DCHECK_LE(operands_count, ComputeOperandsCount()); |
878 int i = 0; | 878 int i = 0; |
879 while (i <= stack_handler_index) { | 879 while (i <= stack_handler_index) { |
880 if (i < stack_handler_index) { | 880 if (i < stack_handler_index) { |
881 // An operand. | 881 // An operand. |
882 ASSERT_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); | 882 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); |
883 Memory::Object_at(GetOperandSlot(i)) = store->get(i); | 883 Memory::Object_at(GetOperandSlot(i)) = store->get(i); |
884 i++; | 884 i++; |
885 } else { | 885 } else { |
886 // A stack handler. | 886 // A stack handler. |
887 ASSERT_EQ(i, stack_handler_index); | 887 DCHECK_EQ(i, stack_handler_index); |
888 // The FixedArray store grows up. The stack grows down. So the operand | 888 // The FixedArray store grows up. The stack grows down. So the operand |
889 // slot for i actually points to the bottom of the top word in the | 889 // slot for i actually points to the bottom of the top word in the |
890 // handler. The base of the StackHandler* is the address of the bottom | 890 // handler. The base of the StackHandler* is the address of the bottom |
891 // word, which will be the last slot that is in the handler. | 891 // word, which will be the last slot that is in the handler. |
892 int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1; | 892 int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1; |
893 StackHandler *handler = | 893 StackHandler *handler = |
894 StackHandler::FromAddress(GetOperandSlot(handler_slot_index)); | 894 StackHandler::FromAddress(GetOperandSlot(handler_slot_index)); |
895 stack_handler_index = handler->Rewind(isolate(), store, i, fp()); | 895 stack_handler_index = handler->Rewind(isolate(), store, i, fp()); |
896 i += StackHandlerConstants::kSlotCount; | 896 i += StackHandlerConstants::kSlotCount; |
897 } | 897 } |
898 } | 898 } |
899 | 899 |
900 for (; i < operands_count; i++) { | 900 for (; i < operands_count; i++) { |
901 ASSERT_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); | 901 DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value()); |
902 Memory::Object_at(GetOperandSlot(i)) = store->get(i); | 902 Memory::Object_at(GetOperandSlot(i)) = store->get(i); |
903 } | 903 } |
904 } | 904 } |
905 | 905 |
906 | 906 |
907 void FrameSummary::Print() { | 907 void FrameSummary::Print() { |
908 PrintF("receiver: "); | 908 PrintF("receiver: "); |
909 receiver_->ShortPrint(); | 909 receiver_->ShortPrint(); |
910 PrintF("\nfunction: "); | 910 PrintF("\nfunction: "); |
911 function_->shared()->DebugName()->ShortPrint(); | 911 function_->shared()->DebugName()->ShortPrint(); |
912 PrintF("\ncode: "); | 912 PrintF("\ncode: "); |
913 code_->ShortPrint(); | 913 code_->ShortPrint(); |
914 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT"); | 914 if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT"); |
915 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT"); | 915 if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT"); |
916 PrintF("\npc: %d\n", offset_); | 916 PrintF("\npc: %d\n", offset_); |
917 } | 917 } |
918 | 918 |
919 | 919 |
920 JSFunction* OptimizedFrame::LiteralAt(FixedArray* literal_array, | 920 JSFunction* OptimizedFrame::LiteralAt(FixedArray* literal_array, |
921 int literal_id) { | 921 int literal_id) { |
922 if (literal_id == Translation::kSelfLiteralId) { | 922 if (literal_id == Translation::kSelfLiteralId) { |
923 return function(); | 923 return function(); |
924 } | 924 } |
925 | 925 |
926 return JSFunction::cast(literal_array->get(literal_id)); | 926 return JSFunction::cast(literal_array->get(literal_id)); |
927 } | 927 } |
928 | 928 |
929 | 929 |
930 void OptimizedFrame::Summarize(List<FrameSummary>* frames) { | 930 void OptimizedFrame::Summarize(List<FrameSummary>* frames) { |
931 ASSERT(frames->length() == 0); | 931 DCHECK(frames->length() == 0); |
932 ASSERT(is_optimized()); | 932 DCHECK(is_optimized()); |
933 | 933 |
934 // Delegate to JS frame in absence of inlining. | 934 // Delegate to JS frame in absence of inlining. |
935 // TODO(turbofan): Revisit once we support inlining. | 935 // TODO(turbofan): Revisit once we support inlining. |
936 if (LookupCode()->is_turbofanned()) { | 936 if (LookupCode()->is_turbofanned()) { |
937 return JavaScriptFrame::Summarize(frames); | 937 return JavaScriptFrame::Summarize(frames); |
938 } | 938 } |
939 | 939 |
940 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 940 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
941 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); | 941 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); |
942 FixedArray* literal_array = data->LiteralArray(); | 942 FixedArray* literal_array = data->LiteralArray(); |
943 | 943 |
944 // BUG(3243555): Since we don't have a lazy-deopt registered at | 944 // BUG(3243555): Since we don't have a lazy-deopt registered at |
945 // throw-statements, we can't use the translation at the call-site of | 945 // throw-statements, we can't use the translation at the call-site of |
946 // throw. An entry with no deoptimization index indicates a call-site | 946 // throw. An entry with no deoptimization index indicates a call-site |
947 // without a lazy-deopt. As a consequence we are not allowed to inline | 947 // without a lazy-deopt. As a consequence we are not allowed to inline |
948 // functions containing throw. | 948 // functions containing throw. |
949 ASSERT(deopt_index != Safepoint::kNoDeoptimizationIndex); | 949 DCHECK(deopt_index != Safepoint::kNoDeoptimizationIndex); |
950 | 950 |
951 TranslationIterator it(data->TranslationByteArray(), | 951 TranslationIterator it(data->TranslationByteArray(), |
952 data->TranslationIndex(deopt_index)->value()); | 952 data->TranslationIndex(deopt_index)->value()); |
953 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 953 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
954 ASSERT(opcode == Translation::BEGIN); | 954 DCHECK(opcode == Translation::BEGIN); |
955 it.Next(); // Drop frame count. | 955 it.Next(); // Drop frame count. |
956 int jsframe_count = it.Next(); | 956 int jsframe_count = it.Next(); |
957 | 957 |
958 // We create the summary in reverse order because the frames | 958 // We create the summary in reverse order because the frames |
959 // in the deoptimization translation are ordered bottom-to-top. | 959 // in the deoptimization translation are ordered bottom-to-top. |
960 bool is_constructor = IsConstructor(); | 960 bool is_constructor = IsConstructor(); |
961 int i = jsframe_count; | 961 int i = jsframe_count; |
962 while (i > 0) { | 962 while (i > 0) { |
963 opcode = static_cast<Translation::Opcode>(it.Next()); | 963 opcode = static_cast<Translation::Opcode>(it.Next()); |
964 if (opcode == Translation::JS_FRAME) { | 964 if (opcode == Translation::JS_FRAME) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1004 } | 1004 } |
1005 | 1005 |
1006 Code* code = function->shared()->code(); | 1006 Code* code = function->shared()->code(); |
1007 DeoptimizationOutputData* output_data = | 1007 DeoptimizationOutputData* output_data = |
1008 DeoptimizationOutputData::cast(code->deoptimization_data()); | 1008 DeoptimizationOutputData::cast(code->deoptimization_data()); |
1009 unsigned entry = Deoptimizer::GetOutputInfo(output_data, | 1009 unsigned entry = Deoptimizer::GetOutputInfo(output_data, |
1010 ast_id, | 1010 ast_id, |
1011 function->shared()); | 1011 function->shared()); |
1012 unsigned pc_offset = | 1012 unsigned pc_offset = |
1013 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; | 1013 FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize; |
1014 ASSERT(pc_offset > 0); | 1014 DCHECK(pc_offset > 0); |
1015 | 1015 |
1016 FrameSummary summary(receiver, function, code, pc_offset, is_constructor); | 1016 FrameSummary summary(receiver, function, code, pc_offset, is_constructor); |
1017 frames->Add(summary); | 1017 frames->Add(summary); |
1018 is_constructor = false; | 1018 is_constructor = false; |
1019 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) { | 1019 } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) { |
1020 // The next encountered JS_FRAME will be marked as a constructor call. | 1020 // The next encountered JS_FRAME will be marked as a constructor call. |
1021 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 1021 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
1022 ASSERT(!is_constructor); | 1022 DCHECK(!is_constructor); |
1023 is_constructor = true; | 1023 is_constructor = true; |
1024 } else { | 1024 } else { |
1025 // Skip over operands to advance to the next opcode. | 1025 // Skip over operands to advance to the next opcode. |
1026 it.Skip(Translation::NumberOfOperandsFor(opcode)); | 1026 it.Skip(Translation::NumberOfOperandsFor(opcode)); |
1027 } | 1027 } |
1028 } | 1028 } |
1029 ASSERT(!is_constructor); | 1029 DCHECK(!is_constructor); |
1030 } | 1030 } |
1031 | 1031 |
1032 | 1032 |
1033 DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData( | 1033 DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData( |
1034 int* deopt_index) { | 1034 int* deopt_index) { |
1035 ASSERT(is_optimized()); | 1035 DCHECK(is_optimized()); |
1036 | 1036 |
1037 JSFunction* opt_function = function(); | 1037 JSFunction* opt_function = function(); |
1038 Code* code = opt_function->code(); | 1038 Code* code = opt_function->code(); |
1039 | 1039 |
1040 // The code object may have been replaced by lazy deoptimization. Fall | 1040 // The code object may have been replaced by lazy deoptimization. Fall |
1041 // back to a slow search in this case to find the original optimized | 1041 // back to a slow search in this case to find the original optimized |
1042 // code object. | 1042 // code object. |
1043 if (!code->contains(pc())) { | 1043 if (!code->contains(pc())) { |
1044 code = isolate()->inner_pointer_to_code_cache()-> | 1044 code = isolate()->inner_pointer_to_code_cache()-> |
1045 GcSafeFindCodeForInnerPointer(pc()); | 1045 GcSafeFindCodeForInnerPointer(pc()); |
1046 } | 1046 } |
1047 ASSERT(code != NULL); | 1047 DCHECK(code != NULL); |
1048 ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION); | 1048 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); |
1049 | 1049 |
1050 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); | 1050 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); |
1051 *deopt_index = safepoint_entry.deoptimization_index(); | 1051 *deopt_index = safepoint_entry.deoptimization_index(); |
1052 ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex); | 1052 DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex); |
1053 | 1053 |
1054 return DeoptimizationInputData::cast(code->deoptimization_data()); | 1054 return DeoptimizationInputData::cast(code->deoptimization_data()); |
1055 } | 1055 } |
1056 | 1056 |
1057 | 1057 |
1058 int OptimizedFrame::GetInlineCount() { | 1058 int OptimizedFrame::GetInlineCount() { |
1059 ASSERT(is_optimized()); | 1059 DCHECK(is_optimized()); |
1060 | 1060 |
1061 // Delegate to JS frame in absence of inlining. | 1061 // Delegate to JS frame in absence of inlining. |
1062 // TODO(turbofan): Revisit once we support inlining. | 1062 // TODO(turbofan): Revisit once we support inlining. |
1063 if (LookupCode()->is_turbofanned()) { | 1063 if (LookupCode()->is_turbofanned()) { |
1064 return JavaScriptFrame::GetInlineCount(); | 1064 return JavaScriptFrame::GetInlineCount(); |
1065 } | 1065 } |
1066 | 1066 |
1067 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 1067 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
1068 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); | 1068 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); |
1069 | 1069 |
1070 TranslationIterator it(data->TranslationByteArray(), | 1070 TranslationIterator it(data->TranslationByteArray(), |
1071 data->TranslationIndex(deopt_index)->value()); | 1071 data->TranslationIndex(deopt_index)->value()); |
1072 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 1072 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
1073 ASSERT(opcode == Translation::BEGIN); | 1073 DCHECK(opcode == Translation::BEGIN); |
1074 USE(opcode); | 1074 USE(opcode); |
1075 it.Next(); // Drop frame count. | 1075 it.Next(); // Drop frame count. |
1076 int jsframe_count = it.Next(); | 1076 int jsframe_count = it.Next(); |
1077 return jsframe_count; | 1077 return jsframe_count; |
1078 } | 1078 } |
1079 | 1079 |
1080 | 1080 |
1081 void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) { | 1081 void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) { |
1082 ASSERT(functions->length() == 0); | 1082 DCHECK(functions->length() == 0); |
1083 ASSERT(is_optimized()); | 1083 DCHECK(is_optimized()); |
1084 | 1084 |
1085 // Delegate to JS frame in absence of inlining. | 1085 // Delegate to JS frame in absence of inlining. |
1086 // TODO(turbofan): Revisit once we support inlining. | 1086 // TODO(turbofan): Revisit once we support inlining. |
1087 if (LookupCode()->is_turbofanned()) { | 1087 if (LookupCode()->is_turbofanned()) { |
1088 return JavaScriptFrame::GetFunctions(functions); | 1088 return JavaScriptFrame::GetFunctions(functions); |
1089 } | 1089 } |
1090 | 1090 |
1091 int deopt_index = Safepoint::kNoDeoptimizationIndex; | 1091 int deopt_index = Safepoint::kNoDeoptimizationIndex; |
1092 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); | 1092 DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index); |
1093 FixedArray* literal_array = data->LiteralArray(); | 1093 FixedArray* literal_array = data->LiteralArray(); |
1094 | 1094 |
1095 TranslationIterator it(data->TranslationByteArray(), | 1095 TranslationIterator it(data->TranslationByteArray(), |
1096 data->TranslationIndex(deopt_index)->value()); | 1096 data->TranslationIndex(deopt_index)->value()); |
1097 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); | 1097 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); |
1098 ASSERT(opcode == Translation::BEGIN); | 1098 DCHECK(opcode == Translation::BEGIN); |
1099 it.Next(); // Drop frame count. | 1099 it.Next(); // Drop frame count. |
1100 int jsframe_count = it.Next(); | 1100 int jsframe_count = it.Next(); |
1101 | 1101 |
1102 // We insert the frames in reverse order because the frames | 1102 // We insert the frames in reverse order because the frames |
1103 // in the deoptimization translation are ordered bottom-to-top. | 1103 // in the deoptimization translation are ordered bottom-to-top. |
1104 while (jsframe_count > 0) { | 1104 while (jsframe_count > 0) { |
1105 opcode = static_cast<Translation::Opcode>(it.Next()); | 1105 opcode = static_cast<Translation::Opcode>(it.Next()); |
1106 if (opcode == Translation::JS_FRAME) { | 1106 if (opcode == Translation::JS_FRAME) { |
1107 jsframe_count--; | 1107 jsframe_count--; |
1108 it.Next(); // Skip ast id. | 1108 it.Next(); // Skip ast id. |
(...skipping 27 matching lines...) Expand all Loading... |
1136 | 1136 |
1137 Code* ArgumentsAdaptorFrame::unchecked_code() const { | 1137 Code* ArgumentsAdaptorFrame::unchecked_code() const { |
1138 return isolate()->builtins()->builtin( | 1138 return isolate()->builtins()->builtin( |
1139 Builtins::kArgumentsAdaptorTrampoline); | 1139 Builtins::kArgumentsAdaptorTrampoline); |
1140 } | 1140 } |
1141 | 1141 |
1142 | 1142 |
1143 Code* InternalFrame::unchecked_code() const { | 1143 Code* InternalFrame::unchecked_code() const { |
1144 const int offset = InternalFrameConstants::kCodeOffset; | 1144 const int offset = InternalFrameConstants::kCodeOffset; |
1145 Object* code = Memory::Object_at(fp() + offset); | 1145 Object* code = Memory::Object_at(fp() + offset); |
1146 ASSERT(code != NULL); | 1146 DCHECK(code != NULL); |
1147 return reinterpret_cast<Code*>(code); | 1147 return reinterpret_cast<Code*>(code); |
1148 } | 1148 } |
1149 | 1149 |
1150 | 1150 |
1151 void StackFrame::PrintIndex(StringStream* accumulator, | 1151 void StackFrame::PrintIndex(StringStream* accumulator, |
1152 PrintMode mode, | 1152 PrintMode mode, |
1153 int index) { | 1153 int index) { |
1154 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index); | 1154 accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index); |
1155 } | 1155 } |
1156 | 1156 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1243 accumulator->Add("\n"); | 1243 accumulator->Add("\n"); |
1244 } | 1244 } |
1245 | 1245 |
1246 // Try to get hold of the context of this frame. | 1246 // Try to get hold of the context of this frame. |
1247 Context* context = NULL; | 1247 Context* context = NULL; |
1248 if (this->context() != NULL && this->context()->IsContext()) { | 1248 if (this->context() != NULL && this->context()->IsContext()) { |
1249 context = Context::cast(this->context()); | 1249 context = Context::cast(this->context()); |
1250 } | 1250 } |
1251 while (context->IsWithContext()) { | 1251 while (context->IsWithContext()) { |
1252 context = context->previous(); | 1252 context = context->previous(); |
1253 ASSERT(context != NULL); | 1253 DCHECK(context != NULL); |
1254 } | 1254 } |
1255 | 1255 |
1256 // Print heap-allocated local variables. | 1256 // Print heap-allocated local variables. |
1257 if (heap_locals_count > 0) { | 1257 if (heap_locals_count > 0) { |
1258 accumulator->Add(" // heap-allocated locals\n"); | 1258 accumulator->Add(" // heap-allocated locals\n"); |
1259 } | 1259 } |
1260 for (int i = 0; i < heap_locals_count; i++) { | 1260 for (int i = 0; i < heap_locals_count; i++) { |
1261 accumulator->Add(" var "); | 1261 accumulator->Add(" var "); |
1262 accumulator->PrintName(scope_info->ContextLocalName(i)); | 1262 accumulator->PrintName(scope_info->ContextLocalName(i)); |
1263 accumulator->Add(" = "); | 1263 accumulator->Add(" = "); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 } | 1324 } |
1325 accumulator->Add("\n"); | 1325 accumulator->Add("\n"); |
1326 } | 1326 } |
1327 | 1327 |
1328 accumulator->Add("}\n\n"); | 1328 accumulator->Add("}\n\n"); |
1329 } | 1329 } |
1330 | 1330 |
1331 | 1331 |
1332 void EntryFrame::Iterate(ObjectVisitor* v) const { | 1332 void EntryFrame::Iterate(ObjectVisitor* v) const { |
1333 StackHandlerIterator it(this, top_handler()); | 1333 StackHandlerIterator it(this, top_handler()); |
1334 ASSERT(!it.done()); | 1334 DCHECK(!it.done()); |
1335 StackHandler* handler = it.handler(); | 1335 StackHandler* handler = it.handler(); |
1336 ASSERT(handler->is_js_entry()); | 1336 DCHECK(handler->is_js_entry()); |
1337 handler->Iterate(v, LookupCode()); | 1337 handler->Iterate(v, LookupCode()); |
1338 #ifdef DEBUG | 1338 #ifdef DEBUG |
1339 // Make sure that the entry frame does not contain more than one | 1339 // Make sure that the entry frame does not contain more than one |
1340 // stack handler. | 1340 // stack handler. |
1341 it.Advance(); | 1341 it.Advance(); |
1342 ASSERT(it.done()); | 1342 DCHECK(it.done()); |
1343 #endif | 1343 #endif |
1344 IteratePc(v, pc_address(), LookupCode()); | 1344 IteratePc(v, pc_address(), LookupCode()); |
1345 } | 1345 } |
1346 | 1346 |
1347 | 1347 |
1348 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { | 1348 void StandardFrame::IterateExpressions(ObjectVisitor* v) const { |
1349 const int offset = StandardFrameConstants::kLastObjectOffset; | 1349 const int offset = StandardFrameConstants::kLastObjectOffset; |
1350 Object** base = &Memory::Object_at(sp()); | 1350 Object** base = &Memory::Object_at(sp()); |
1351 Object** limit = &Memory::Object_at(fp() + offset) + 1; | 1351 Object** limit = &Memory::Object_at(fp() + offset) + 1; |
1352 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { | 1352 for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 | 1412 |
1413 UNREACHABLE(); | 1413 UNREACHABLE(); |
1414 return NULL; | 1414 return NULL; |
1415 } | 1415 } |
1416 | 1416 |
1417 | 1417 |
1418 // ------------------------------------------------------------------------- | 1418 // ------------------------------------------------------------------------- |
1419 | 1419 |
1420 | 1420 |
1421 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { | 1421 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) { |
1422 ASSERT(n >= 0); | 1422 DCHECK(n >= 0); |
1423 for (int i = 0; i <= n; i++) { | 1423 for (int i = 0; i <= n; i++) { |
1424 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); | 1424 while (!iterator_.frame()->is_java_script()) iterator_.Advance(); |
1425 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); | 1425 if (i == n) return JavaScriptFrame::cast(iterator_.frame()); |
1426 iterator_.Advance(); | 1426 iterator_.Advance(); |
1427 } | 1427 } |
1428 UNREACHABLE(); | 1428 UNREACHABLE(); |
1429 return NULL; | 1429 return NULL; |
1430 } | 1430 } |
1431 | 1431 |
1432 | 1432 |
1433 // ------------------------------------------------------------------------- | 1433 // ------------------------------------------------------------------------- |
1434 | 1434 |
1435 | 1435 |
1436 static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) { | 1436 static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) { |
1437 MapWord map_word = object->map_word(); | 1437 MapWord map_word = object->map_word(); |
1438 return map_word.IsForwardingAddress() ? | 1438 return map_word.IsForwardingAddress() ? |
1439 map_word.ToForwardingAddress()->map() : map_word.ToMap(); | 1439 map_word.ToForwardingAddress()->map() : map_word.ToMap(); |
1440 } | 1440 } |
1441 | 1441 |
1442 | 1442 |
1443 static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) { | 1443 static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) { |
1444 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object)); | 1444 return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object)); |
1445 } | 1445 } |
1446 | 1446 |
1447 | 1447 |
1448 #ifdef DEBUG | 1448 #ifdef DEBUG |
1449 static bool GcSafeCodeContains(HeapObject* code, Address addr) { | 1449 static bool GcSafeCodeContains(HeapObject* code, Address addr) { |
1450 Map* map = GcSafeMapOfCodeSpaceObject(code); | 1450 Map* map = GcSafeMapOfCodeSpaceObject(code); |
1451 ASSERT(map == code->GetHeap()->code_map()); | 1451 DCHECK(map == code->GetHeap()->code_map()); |
1452 Address start = code->address(); | 1452 Address start = code->address(); |
1453 Address end = code->address() + code->SizeFromMap(map); | 1453 Address end = code->address() + code->SizeFromMap(map); |
1454 return start <= addr && addr < end; | 1454 return start <= addr && addr < end; |
1455 } | 1455 } |
1456 #endif | 1456 #endif |
1457 | 1457 |
1458 | 1458 |
1459 Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object, | 1459 Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object, |
1460 Address inner_pointer) { | 1460 Address inner_pointer) { |
1461 Code* code = reinterpret_cast<Code*>(object); | 1461 Code* code = reinterpret_cast<Code*>(object); |
1462 ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer)); | 1462 DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer)); |
1463 return code; | 1463 return code; |
1464 } | 1464 } |
1465 | 1465 |
1466 | 1466 |
1467 Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer( | 1467 Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer( |
1468 Address inner_pointer) { | 1468 Address inner_pointer) { |
1469 Heap* heap = isolate_->heap(); | 1469 Heap* heap = isolate_->heap(); |
1470 // Check if the inner pointer points into a large object chunk. | 1470 // Check if the inner pointer points into a large object chunk. |
1471 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer); | 1471 LargePage* large_page = heap->lo_space()->FindPage(inner_pointer); |
1472 if (large_page != NULL) { | 1472 if (large_page != NULL) { |
(...skipping 20 matching lines...) Expand all Loading... |
1493 Address next_addr = addr + obj_size; | 1493 Address next_addr = addr + obj_size; |
1494 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer); | 1494 if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer); |
1495 addr = next_addr; | 1495 addr = next_addr; |
1496 } | 1496 } |
1497 } | 1497 } |
1498 | 1498 |
1499 | 1499 |
1500 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* | 1500 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* |
1501 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) { | 1501 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) { |
1502 isolate_->counters()->pc_to_code()->Increment(); | 1502 isolate_->counters()->pc_to_code()->Increment(); |
1503 ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize)); | 1503 DCHECK(IsPowerOf2(kInnerPointerToCodeCacheSize)); |
1504 uint32_t hash = ComputeIntegerHash( | 1504 uint32_t hash = ComputeIntegerHash( |
1505 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)), | 1505 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)), |
1506 v8::internal::kZeroHashSeed); | 1506 v8::internal::kZeroHashSeed); |
1507 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1); | 1507 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1); |
1508 InnerPointerToCodeCacheEntry* entry = cache(index); | 1508 InnerPointerToCodeCacheEntry* entry = cache(index); |
1509 if (entry->inner_pointer == inner_pointer) { | 1509 if (entry->inner_pointer == inner_pointer) { |
1510 isolate_->counters()->pc_to_code_cached()->Increment(); | 1510 isolate_->counters()->pc_to_code_cached()->Increment(); |
1511 ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer)); | 1511 DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer)); |
1512 } else { | 1512 } else { |
1513 // Because this code may be interrupted by a profiling signal that | 1513 // Because this code may be interrupted by a profiling signal that |
1514 // also queries the cache, we cannot update inner_pointer before the code | 1514 // also queries the cache, we cannot update inner_pointer before the code |
1515 // has been set. Otherwise, we risk trying to use a cache entry before | 1515 // has been set. Otherwise, we risk trying to use a cache entry before |
1516 // the code has been computed. | 1516 // the code has been computed. |
1517 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer); | 1517 entry->code = GcSafeFindCodeForInnerPointer(inner_pointer); |
1518 entry->safepoint_entry.Reset(); | 1518 entry->safepoint_entry.Reset(); |
1519 entry->inner_pointer = inner_pointer; | 1519 entry->inner_pointer = inner_pointer; |
1520 } | 1520 } |
1521 return entry; | 1521 return entry; |
1522 } | 1522 } |
1523 | 1523 |
1524 | 1524 |
1525 // ------------------------------------------------------------------------- | 1525 // ------------------------------------------------------------------------- |
1526 | 1526 |
1527 | 1527 |
1528 void StackHandler::Unwind(Isolate* isolate, | 1528 void StackHandler::Unwind(Isolate* isolate, |
1529 FixedArray* array, | 1529 FixedArray* array, |
1530 int offset, | 1530 int offset, |
1531 int previous_handler_offset) const { | 1531 int previous_handler_offset) const { |
1532 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5); | 1532 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5); |
1533 ASSERT_LE(0, offset); | 1533 DCHECK_LE(0, offset); |
1534 ASSERT_GE(array->length(), offset + StackHandlerConstants::kSlotCount); | 1534 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount); |
1535 // Unwinding a stack handler into an array chains it in the opposite | 1535 // Unwinding a stack handler into an array chains it in the opposite |
1536 // direction, re-using the "next" slot as a "previous" link, so that stack | 1536 // direction, re-using the "next" slot as a "previous" link, so that stack |
1537 // handlers can be later re-wound in the correct order. Decode the "state" | 1537 // handlers can be later re-wound in the correct order. Decode the "state" |
1538 // slot into "index" and "kind" and store them separately, using the fp slot. | 1538 // slot into "index" and "kind" and store them separately, using the fp slot. |
1539 array->set(offset, Smi::FromInt(previous_handler_offset)); // next | 1539 array->set(offset, Smi::FromInt(previous_handler_offset)); // next |
1540 array->set(offset + 1, *code_address()); // code | 1540 array->set(offset + 1, *code_address()); // code |
1541 array->set(offset + 2, Smi::FromInt(static_cast<int>(index()))); // state | 1541 array->set(offset + 2, Smi::FromInt(static_cast<int>(index()))); // state |
1542 array->set(offset + 3, *context_address()); // context | 1542 array->set(offset + 3, *context_address()); // context |
1543 array->set(offset + 4, Smi::FromInt(static_cast<int>(kind()))); // fp | 1543 array->set(offset + 4, Smi::FromInt(static_cast<int>(kind()))); // fp |
1544 | 1544 |
1545 *isolate->handler_address() = next()->address(); | 1545 *isolate->handler_address() = next()->address(); |
1546 } | 1546 } |
1547 | 1547 |
1548 | 1548 |
1549 int StackHandler::Rewind(Isolate* isolate, | 1549 int StackHandler::Rewind(Isolate* isolate, |
1550 FixedArray* array, | 1550 FixedArray* array, |
1551 int offset, | 1551 int offset, |
1552 Address fp) { | 1552 Address fp) { |
1553 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5); | 1553 STATIC_ASSERT(StackHandlerConstants::kSlotCount >= 5); |
1554 ASSERT_LE(0, offset); | 1554 DCHECK_LE(0, offset); |
1555 ASSERT_GE(array->length(), offset + StackHandlerConstants::kSlotCount); | 1555 DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount); |
1556 Smi* prev_handler_offset = Smi::cast(array->get(offset)); | 1556 Smi* prev_handler_offset = Smi::cast(array->get(offset)); |
1557 Code* code = Code::cast(array->get(offset + 1)); | 1557 Code* code = Code::cast(array->get(offset + 1)); |
1558 Smi* smi_index = Smi::cast(array->get(offset + 2)); | 1558 Smi* smi_index = Smi::cast(array->get(offset + 2)); |
1559 Object* context = array->get(offset + 3); | 1559 Object* context = array->get(offset + 3); |
1560 Smi* smi_kind = Smi::cast(array->get(offset + 4)); | 1560 Smi* smi_kind = Smi::cast(array->get(offset + 4)); |
1561 | 1561 |
1562 unsigned state = KindField::encode(static_cast<Kind>(smi_kind->value())) | | 1562 unsigned state = KindField::encode(static_cast<Kind>(smi_kind->value())) | |
1563 IndexField::encode(static_cast<unsigned>(smi_index->value())); | 1563 IndexField::encode(static_cast<unsigned>(smi_index->value())); |
1564 | 1564 |
1565 Memory::Address_at(address() + StackHandlerConstants::kNextOffset) = | 1565 Memory::Address_at(address() + StackHandlerConstants::kNextOffset) = |
(...skipping 22 matching lines...) Expand all Loading... |
1588 }; | 1588 }; |
1589 | 1589 |
1590 JSCallerSavedCodeData caller_saved_code_data; | 1590 JSCallerSavedCodeData caller_saved_code_data; |
1591 | 1591 |
1592 void SetUpJSCallerSavedCodeData() { | 1592 void SetUpJSCallerSavedCodeData() { |
1593 int i = 0; | 1593 int i = 0; |
1594 for (int r = 0; r < kNumRegs; r++) | 1594 for (int r = 0; r < kNumRegs; r++) |
1595 if ((kJSCallerSaved & (1 << r)) != 0) | 1595 if ((kJSCallerSaved & (1 << r)) != 0) |
1596 caller_saved_code_data.reg_code[i++] = r; | 1596 caller_saved_code_data.reg_code[i++] = r; |
1597 | 1597 |
1598 ASSERT(i == kNumJSCallerSaved); | 1598 DCHECK(i == kNumJSCallerSaved); |
1599 } | 1599 } |
1600 | 1600 |
1601 | 1601 |
1602 int JSCallerSavedCode(int n) { | 1602 int JSCallerSavedCode(int n) { |
1603 ASSERT(0 <= n && n < kNumJSCallerSaved); | 1603 DCHECK(0 <= n && n < kNumJSCallerSaved); |
1604 return caller_saved_code_data.reg_code[n]; | 1604 return caller_saved_code_data.reg_code[n]; |
1605 } | 1605 } |
1606 | 1606 |
1607 | 1607 |
1608 #define DEFINE_WRAPPER(type, field) \ | 1608 #define DEFINE_WRAPPER(type, field) \ |
1609 class field##_Wrapper : public ZoneObject { \ | 1609 class field##_Wrapper : public ZoneObject { \ |
1610 public: /* NOLINT */ \ | 1610 public: /* NOLINT */ \ |
1611 field##_Wrapper(const field& original) : frame_(original) { \ | 1611 field##_Wrapper(const field& original) : frame_(original) { \ |
1612 } \ | 1612 } \ |
1613 field frame_; \ | 1613 field frame_; \ |
(...skipping 22 matching lines...) Expand all Loading... |
1636 ZoneList<StackFrame*> list(10, zone); | 1636 ZoneList<StackFrame*> list(10, zone); |
1637 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { | 1637 for (StackFrameIterator it(isolate); !it.done(); it.Advance()) { |
1638 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); | 1638 StackFrame* frame = AllocateFrameCopy(it.frame(), zone); |
1639 list.Add(frame, zone); | 1639 list.Add(frame, zone); |
1640 } | 1640 } |
1641 return list.ToVector(); | 1641 return list.ToVector(); |
1642 } | 1642 } |
1643 | 1643 |
1644 | 1644 |
1645 } } // namespace v8::internal | 1645 } } // namespace v8::internal |
OLD | NEW |