1// Copyright 2015 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "src/debug/debug-frames.h" 6 7#include "src/frames-inl.h" 8 9namespace v8 { 10namespace internal { 11 12FrameInspector::FrameInspector(JavaScriptFrame* frame, 13 int inlined_jsframe_index, Isolate* isolate) 14 : frame_(frame), deoptimized_frame_(NULL), isolate_(isolate) { 15 has_adapted_arguments_ = frame_->has_adapted_arguments(); 16 is_bottommost_ = inlined_jsframe_index == 0; 17 is_optimized_ = frame_->is_optimized(); 18 // Calculate the deoptimized frame. 19 if (frame->is_optimized()) { 20 // TODO(turbofan): Revisit once we support deoptimization. 21 if (frame->LookupCode()->is_turbofanned() && 22 frame->function()->shared()->asm_function() && 23 !FLAG_turbo_asm_deoptimization) { 24 is_optimized_ = false; 25 return; 26 } 27 28 deoptimized_frame_ = Deoptimizer::DebuggerInspectableFrame( 29 frame, inlined_jsframe_index, isolate); 30 } 31} 32 33 34FrameInspector::~FrameInspector() { 35 // Get rid of the calculated deoptimized frame if any. 36 if (deoptimized_frame_ != NULL) { 37 Deoptimizer::DeleteDebuggerInspectableFrame(deoptimized_frame_, isolate_); 38 } 39} 40 41 42int FrameInspector::GetParametersCount() { 43 return is_optimized_ ? deoptimized_frame_->parameters_count() 44 : frame_->ComputeParametersCount(); 45} 46 47 48Object* FrameInspector::GetFunction() { 49 return is_optimized_ ? deoptimized_frame_->GetFunction() : frame_->function(); 50} 51 52 53Object* FrameInspector::GetParameter(int index) { 54 return is_optimized_ ? deoptimized_frame_->GetParameter(index) 55 : frame_->GetParameter(index); 56} 57 58 59Object* FrameInspector::GetExpression(int index) { 60 // TODO(turbofan): Revisit once we support deoptimization. 61 if (frame_->LookupCode()->is_turbofanned() && 62 frame_->function()->shared()->asm_function() && 63 !FLAG_turbo_asm_deoptimization) { 64 return isolate_->heap()->undefined_value(); 65 } 66 return is_optimized_ ? deoptimized_frame_->GetExpression(index) 67 : frame_->GetExpression(index); 68} 69 70 71int FrameInspector::GetSourcePosition() { 72 return is_optimized_ ? deoptimized_frame_->GetSourcePosition() 73 : frame_->LookupCode()->SourcePosition(frame_->pc()); 74} 75 76 77bool FrameInspector::IsConstructor() { 78 return is_optimized_ && !is_bottommost_ 79 ? deoptimized_frame_->HasConstructStub() 80 : frame_->IsConstructor(); 81} 82 83 84Object* FrameInspector::GetContext() { 85 return is_optimized_ ? deoptimized_frame_->GetContext() : frame_->context(); 86} 87 88 89// To inspect all the provided arguments the frame might need to be 90// replaced with the arguments frame. 91void FrameInspector::SetArgumentsFrame(JavaScriptFrame* frame) { 92 DCHECK(has_adapted_arguments_); 93 frame_ = frame; 94 is_optimized_ = frame_->is_optimized(); 95 DCHECK(!is_optimized_); 96} 97 98 99// Create a plain JSObject which materializes the local scope for the specified 100// frame. 101void FrameInspector::MaterializeStackLocals(Handle<JSObject> target, 102 Handle<ScopeInfo> scope_info) { 103 HandleScope scope(isolate_); 104 // First fill all parameters. 105 for (int i = 0; i < scope_info->ParameterCount(); ++i) { 106 // Do not materialize the parameter if it is shadowed by a context local. 107 // TODO(yangguo): check whether this is necessary, now that we materialize 108 // context locals as well. 109 Handle<String> name(scope_info->ParameterName(i)); 110 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; 111 112 Handle<Object> value(i < GetParametersCount() 113 ? GetParameter(i) 114 : isolate_->heap()->undefined_value(), 115 isolate_); 116 DCHECK(!value->IsTheHole()); 117 118 JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); 119 } 120 121 // Second fill all stack locals. 122 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { 123 if (scope_info->LocalIsSynthetic(i)) continue; 124 Handle<String> name(scope_info->StackLocalName(i)); 125 Handle<Object> value(GetExpression(scope_info->StackLocalIndex(i)), 126 isolate_); 127 if (value->IsTheHole()) value = isolate_->factory()->undefined_value(); 128 129 JSObject::SetOwnPropertyIgnoreAttributes(target, name, value, NONE).Check(); 130 } 131} 132 133 134void FrameInspector::MaterializeStackLocals(Handle<JSObject> target, 135 Handle<JSFunction> function) { 136 Handle<SharedFunctionInfo> shared(function->shared()); 137 Handle<ScopeInfo> scope_info(shared->scope_info()); 138 MaterializeStackLocals(target, scope_info); 139} 140 141 142void FrameInspector::UpdateStackLocalsFromMaterializedObject( 143 Handle<JSObject> target, Handle<ScopeInfo> scope_info) { 144 if (is_optimized_) { 145 // Optimized frames are not supported. Simply give up. 146 return; 147 } 148 149 HandleScope scope(isolate_); 150 151 // Parameters. 152 for (int i = 0; i < scope_info->ParameterCount(); ++i) { 153 // Shadowed parameters were not materialized. 154 Handle<String> name(scope_info->ParameterName(i)); 155 if (ParameterIsShadowedByContextLocal(scope_info, name)) continue; 156 157 DCHECK(!frame_->GetParameter(i)->IsTheHole()); 158 Handle<Object> value = 159 Object::GetPropertyOrElement(target, name).ToHandleChecked(); 160 frame_->SetParameterValue(i, *value); 161 } 162 163 // Stack locals. 164 for (int i = 0; i < scope_info->StackLocalCount(); ++i) { 165 if (scope_info->LocalIsSynthetic(i)) continue; 166 int index = scope_info->StackLocalIndex(i); 167 if (frame_->GetExpression(index)->IsTheHole()) continue; 168 Handle<Object> value = 169 Object::GetPropertyOrElement( 170 target, handle(scope_info->StackLocalName(i), isolate_)) 171 .ToHandleChecked(); 172 frame_->SetExpression(index, *value); 173 } 174} 175 176 177bool FrameInspector::ParameterIsShadowedByContextLocal( 178 Handle<ScopeInfo> info, Handle<String> parameter_name) { 179 VariableMode mode; 180 InitializationFlag init_flag; 181 MaybeAssignedFlag maybe_assigned_flag; 182 return ScopeInfo::ContextSlotIndex(info, parameter_name, &mode, &init_flag, 183 &maybe_assigned_flag) != -1; 184} 185 186 187SaveContext* DebugFrameHelper::FindSavedContextForFrame( 188 Isolate* isolate, JavaScriptFrame* frame) { 189 SaveContext* save = isolate->save_context(); 190 while (save != NULL && !save->IsBelowFrame(frame)) { 191 save = save->prev(); 192 } 193 DCHECK(save != NULL); 194 return save; 195} 196 197 198int DebugFrameHelper::FindIndexedNonNativeFrame(JavaScriptFrameIterator* it, 199 int index) { 200 int count = -1; 201 for (; !it->done(); it->Advance()) { 202 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 203 it->frame()->Summarize(&frames); 204 for (int i = frames.length() - 1; i >= 0; i--) { 205 // Omit functions from native and extension scripts. 206 if (!frames[i].function()->shared()->IsSubjectToDebugging()) continue; 207 if (++count == index) return i; 208 } 209 } 210 return -1; 211} 212 213 214} // namespace internal 215} // namespace v8 216