Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(384)

Side by Side Diff: runtime/vm/exceptions.cc

Issue 2734323003: Re-landing of "replace TrySync with Metadata". (Closed)
Patch Set: Address review comments Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/exceptions.h ('k') | runtime/vm/fixed_cache.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/exceptions.h" 5 #include "vm/exceptions.h"
6 6
7 #include "platform/address_sanitizer.h" 7 #include "platform/address_sanitizer.h"
8 8
9 #include "lib/stacktrace.h" 9 #include "lib/stacktrace.h"
10 10
11 #include "vm/dart_api_impl.h" 11 #include "vm/dart_api_impl.h"
12 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
13 #include "vm/datastream.h"
13 #include "vm/debugger.h" 14 #include "vm/debugger.h"
15 #include "vm/deopt_instructions.h"
14 #include "vm/flags.h" 16 #include "vm/flags.h"
15 #include "vm/log.h" 17 #include "vm/log.h"
16 #include "vm/longjump.h" 18 #include "vm/longjump.h"
17 #include "vm/object.h" 19 #include "vm/object.h"
18 #include "vm/object_store.h" 20 #include "vm/object_store.h"
19 #include "vm/stack_frame.h" 21 #include "vm/stack_frame.h"
20 #include "vm/stub_code.h" 22 #include "vm/stub_code.h"
21 #include "vm/symbols.h" 23 #include "vm/symbols.h"
22 #include "vm/tags.h" 24 #include "vm/tags.h"
23 25
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 code = frame->LookupDartCode(); 138 code = frame->LookupDartCode();
137 ASSERT(code.ContainsInstructionAt(frame->pc())); 139 ASSERT(code.ContainsInstructionAt(frame->pc()));
138 offset = Smi::New(frame->pc() - code.PayloadStart()); 140 offset = Smi::New(frame->pc() - code.PayloadStart());
139 builder->AddFrame(code, offset); 141 builder->AddFrame(code, offset);
140 } 142 }
141 frame = frames.NextFrame(); 143 frame = frames.NextFrame();
142 } 144 }
143 } 145 }
144 146
145 147
146 // Iterate through the stack frames and try to find a frame with an 148 static RawObject** VariableAt(uword fp, int stack_slot) {
147 // exception handler. Once found, set the pc, sp and fp so that execution 149 #if defined(TARGET_ARCH_DBC)
148 // can continue in that frame. Sets 'needs_stacktrace' if there is no 150 return reinterpret_cast<RawObject**>(fp + stack_slot * kWordSize);
149 // cath-all handler or if a stack-trace is specified in the catch. 151 #else
150 static bool FindExceptionHandler(Thread* thread, 152 if (stack_slot < 0) {
151 uword* handler_pc, 153 return reinterpret_cast<RawObject**>(ParamAddress(fp, -stack_slot));
152 uword* handler_sp, 154 } else {
153 uword* handler_fp, 155 return reinterpret_cast<RawObject**>(
154 bool* needs_stacktrace) { 156 LocalVarAddress(fp, kFirstLocalSlotFromFp - stack_slot));
155 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); 157 }
156 StackFrame* frame = frames.NextFrame(); 158 #endif
157 if (frame == NULL) return false; // No Dart frame. 159 }
158 bool handler_pc_set = false; 160
159 *needs_stacktrace = false; 161
160 bool is_catch_all = false; 162 class ExceptionHandlerFinder : public StackResource {
161 uword temp_handler_pc = kUwordMax; 163 public:
162 while (!frame->IsEntryFrame()) { 164 explicit ExceptionHandlerFinder(Thread* thread)
163 if (frame->IsDartFrame()) { 165 : StackResource(thread), thread_(thread), cache_(NULL), metadata_(NULL) {}
164 if (frame->FindExceptionHandler(thread, &temp_handler_pc, 166
165 needs_stacktrace, &is_catch_all)) { 167 // Iterate through the stack frames and try to find a frame with an
166 if (!handler_pc_set) { 168 // exception handler. Once found, set the pc, sp and fp so that execution
167 handler_pc_set = true; 169 // can continue in that frame. Sets 'needs_stacktrace' if there is no
168 *handler_pc = temp_handler_pc; 170 // cath-all handler or if a stack-trace is specified in the catch.
169 *handler_sp = frame->sp(); 171 bool Find() {
170 *handler_fp = frame->fp(); 172 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
171 } 173 StackFrame* frame = frames.NextFrame();
172 if (*needs_stacktrace || is_catch_all) { 174 if (frame == NULL) return false; // No Dart frame.
173 return true; 175 handler_pc_set_ = false;
174 } 176 needs_stacktrace = false;
177 bool is_catch_all = false;
178 uword temp_handler_pc = kUwordMax;
179 bool is_optimized = false;
180 code_ = NULL;
181 cache_ = thread_->isolate()->catch_entry_state_cache();
182
183 while (!frame->IsEntryFrame()) {
184 if (frame->IsDartFrame()) {
185 if (frame->FindExceptionHandler(thread_, &temp_handler_pc,
186 &needs_stacktrace, &is_catch_all,
187 &is_optimized)) {
188 if (!handler_pc_set_) {
189 handler_pc_set_ = true;
190 handler_pc = temp_handler_pc;
191 handler_sp = frame->sp();
192 handler_fp = frame->fp();
193 if (is_optimized) {
194 pc_ = frame->pc();
195 code_ = &Code::Handle(frame->LookupDartCode());
196 CatchEntryState* state = cache_->Lookup(pc_);
197 if (state != NULL) cached_ = *state;
198 #if !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
199 intptr_t num_vars = Smi::Value(code_->variables());
200 if (cached_.Empty()) GetMetaDataFromDeopt(num_vars, frame);
201 #else
202 if (cached_.Empty()) ReadCompressedMetaData();
203 #endif // !defined(DART_PRECOMPILED_RUNTIME) && !defined(DART_PRECOMPILER)
204 }
205 }
206 if (needs_stacktrace || is_catch_all) {
207 return true;
208 }
209 }
210 } // if frame->IsDartFrame
211 frame = frames.NextFrame();
212 ASSERT(frame != NULL);
213 } // while !frame->IsEntryFrame
214 ASSERT(frame->IsEntryFrame());
215 if (!handler_pc_set_) {
216 handler_pc = frame->pc();
217 handler_sp = frame->sp();
218 handler_fp = frame->fp();
219 }
220 // No catch-all encountered, needs stacktrace.
221 needs_stacktrace = true;
222 return handler_pc_set_;
223 }
224
225 void TrySync() {
226 if (code_ == NULL || !code_->is_optimized()) {
227 return;
228 }
229 if (!cached_.Empty()) {
230 // Cache hit.
231 TrySyncCached(&cached_);
232 } else {
233 // New cache entry.
234 CatchEntryState m(metadata_);
235 TrySyncCached(&m);
236 cache_->Insert(pc_, m);
237 }
238 }
239
240 void TrySyncCached(CatchEntryState* md) {
241 uword fp = handler_fp;
242 ObjectPool* pool = NULL;
243 intptr_t pairs = md->Pairs();
244 for (int j = 0; j < pairs; j++) {
245 intptr_t src = md->Src(j);
246 intptr_t dest = md->Dest(j);
247 if (md->isMove(j)) {
248 *VariableAt(fp, dest) = *VariableAt(fp, src);
249 } else {
250 if (pool == NULL) {
251 pool = &ObjectPool::Handle(code_->object_pool());
252 }
253 RawObject* obj = pool->ObjectAt(src);
254 *VariableAt(fp, dest) = obj;
175 } 255 }
176 } // if frame->IsDartFrame 256 }
177 frame = frames.NextFrame(); 257 }
178 ASSERT(frame != NULL); 258
179 } // while !frame->IsEntryFrame 259 #if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
180 ASSERT(frame->IsEntryFrame()); 260 void ReadCompressedMetaData() {
181 if (!handler_pc_set) { 261 intptr_t pc_offset = pc_ - code_->PayloadStart();
182 *handler_pc = frame->pc(); 262 const TypedData& td = TypedData::Handle(code_->catch_entry_state_maps());
183 *handler_sp = frame->sp(); 263 NoSafepointScope no_safepoint;
184 *handler_fp = frame->fp(); 264 ReadStream stream(static_cast<uint8_t*>(td.DataAddr(0)), td.Length());
185 } 265
186 // No catch-all encountered, needs stacktrace. 266 bool found_metadata = false;
187 *needs_stacktrace = true; 267 while (stream.PendingBytes() > 0) {
188 return handler_pc_set; 268 intptr_t target_pc_offset = Reader::Read(&stream);
189 } 269 intptr_t variables = Reader::Read(&stream);
270 intptr_t suffix_length = Reader::Read(&stream);
271 intptr_t suffix_offset = Reader::Read(&stream);
272 if (pc_offset == target_pc_offset) {
273 metadata_ = new intptr_t[2 * (variables + suffix_length) + 1];
274 metadata_[0] = variables + suffix_length;
275 for (int j = 0; j < variables; j++) {
276 intptr_t src = Reader::Read(&stream);
277 intptr_t dest = Reader::Read(&stream);
278 metadata_[1 + 2 * j] = src;
279 metadata_[2 + 2 * j] = dest;
280 }
281 ReadCompressedSuffix(&stream, suffix_offset, suffix_length, metadata_,
282 2 * variables + 1);
283 found_metadata = true;
284 break;
285 } else {
286 for (intptr_t j = 0; j < 2 * variables; j++) {
287 Reader::Read(&stream);
288 }
289 }
290 }
291 ASSERT(found_metadata);
292 }
293
294 void ReadCompressedSuffix(ReadStream* stream,
295 intptr_t offset,
296 intptr_t length,
297 intptr_t* target,
298 intptr_t target_offset) {
299 stream->SetPosition(offset);
300 Reader::Read(stream); // skip pc_offset
301 Reader::Read(stream); // skip variables
302 intptr_t suffix_length = Reader::Read(stream);
303 intptr_t suffix_offset = Reader::Read(stream);
304 intptr_t to_read = length - suffix_length;
305 for (int j = 0; j < to_read; j++) {
306 target[target_offset + 2 * j] = Reader::Read(stream);
307 target[target_offset + 2 * j + 1] = Reader::Read(stream);
308 }
309 if (suffix_length > 0) {
310 ReadCompressedSuffix(stream, suffix_offset, suffix_length, target,
311 target_offset + to_read * 2);
312 }
313 }
314
315 #else
316 void GetMetaDataFromDeopt(intptr_t num_vars, StackFrame* frame) {
317 Isolate* isolate = thread_->isolate();
318 DeoptContext* deopt_context =
319 new DeoptContext(frame, *code_, DeoptContext::kDestIsAllocated, NULL,
320 NULL, true, false /* deoptimizing_code */);
321 isolate->set_deopt_context(deopt_context);
322
323 metadata_ = deopt_context->CatchEntryState(num_vars);
324
325 isolate->set_deopt_context(NULL);
326 delete deopt_context;
327 }
328 #endif // defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
329
330 bool needs_stacktrace;
331 uword handler_pc;
332 uword handler_sp;
333 uword handler_fp;
334
335 private:
336 typedef ReadStream::Raw<sizeof(intptr_t), intptr_t> Reader;
337 Thread* thread_;
338 CatchEntryStateCache* cache_;
339 Code* code_;
340 bool handler_pc_set_;
341 intptr_t* metadata_; // MetaData generated from deopt.
342 CatchEntryState cached_; // Value of per PC MetaData cache.
343 intptr_t pc_; // Current pc in the handler frame.
344 };
190 345
191 346
192 static void FindErrorHandler(uword* handler_pc, 347 static void FindErrorHandler(uword* handler_pc,
193 uword* handler_sp, 348 uword* handler_sp,
194 uword* handler_fp) { 349 uword* handler_fp) {
195 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); 350 StackFrameIterator frames(StackFrameIterator::kDontValidateFrames);
196 StackFrame* frame = frames.NextFrame(); 351 StackFrame* frame = frames.NextFrame();
197 ASSERT(frame != NULL); 352 ASSERT(frame != NULL);
198 while (!frame->IsEntryFrame()) { 353 while (!frame->IsEntryFrame()) {
199 frame = frames.NextFrame(); 354 frame = frames.NextFrame();
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 Isolate* isolate = thread->isolate(); 539 Isolate* isolate = thread->isolate();
385 bool use_preallocated_stacktrace = false; 540 bool use_preallocated_stacktrace = false;
386 Instance& exception = Instance::Handle(zone, incoming_exception.raw()); 541 Instance& exception = Instance::Handle(zone, incoming_exception.raw());
387 if (exception.IsNull()) { 542 if (exception.IsNull()) {
388 exception ^= 543 exception ^=
389 Exceptions::Create(Exceptions::kNullThrown, Object::empty_array()); 544 Exceptions::Create(Exceptions::kNullThrown, Object::empty_array());
390 } else if (exception.raw() == isolate->object_store()->out_of_memory() || 545 } else if (exception.raw() == isolate->object_store()->out_of_memory() ||
391 exception.raw() == isolate->object_store()->stack_overflow()) { 546 exception.raw() == isolate->object_store()->stack_overflow()) {
392 use_preallocated_stacktrace = true; 547 use_preallocated_stacktrace = true;
393 } 548 }
394 uword handler_pc = 0;
395 uword handler_sp = 0;
396 uword handler_fp = 0;
397 Instance& stacktrace = Instance::Handle(zone);
398 bool handler_exists = false;
399 bool handler_needs_stacktrace = false;
400 // Find the exception handler and determine if the handler needs a 549 // Find the exception handler and determine if the handler needs a
401 // stacktrace. 550 // stacktrace.
402 handler_exists = FindExceptionHandler(thread, &handler_pc, &handler_sp, 551 ExceptionHandlerFinder finder(thread);
403 &handler_fp, &handler_needs_stacktrace); 552 bool handler_exists = finder.Find();
553 uword handler_pc = finder.handler_pc;
554 uword handler_sp = finder.handler_sp;
555 uword handler_fp = finder.handler_fp;
556 bool handler_needs_stacktrace = finder.needs_stacktrace;
557 Instance& stacktrace = Instance::Handle(zone);
404 if (use_preallocated_stacktrace) { 558 if (use_preallocated_stacktrace) {
405 if (handler_pc == 0) { 559 if (handler_pc == 0) {
406 // No Dart frame. 560 // No Dart frame.
407 ASSERT(incoming_exception.raw() == 561 ASSERT(incoming_exception.raw() ==
408 isolate->object_store()->out_of_memory()); 562 isolate->object_store()->out_of_memory());
409 const UnhandledException& error = UnhandledException::Handle( 563 const UnhandledException& error = UnhandledException::Handle(
410 zone, isolate->object_store()->preallocated_unhandled_exception()); 564 zone, isolate->object_store()->preallocated_unhandled_exception());
411 thread->long_jump_base()->Jump(1, error); 565 thread->long_jump_base()->Jump(1, error);
412 UNREACHABLE(); 566 UNREACHABLE();
413 } 567 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 // then we expect to at least have the dart entry frame on the 602 // then we expect to at least have the dart entry frame on the
449 // stack as Exceptions::Throw should happen only after a dart 603 // stack as Exceptions::Throw should happen only after a dart
450 // invocation has been done. 604 // invocation has been done.
451 ASSERT(handler_pc != 0); 605 ASSERT(handler_pc != 0);
452 606
453 if (FLAG_print_stacktrace_at_throw) { 607 if (FLAG_print_stacktrace_at_throw) {
454 THR_Print("Exception '%s' thrown:\n", exception.ToCString()); 608 THR_Print("Exception '%s' thrown:\n", exception.ToCString());
455 THR_Print("%s\n", stacktrace.ToCString()); 609 THR_Print("%s\n", stacktrace.ToCString());
456 } 610 }
457 if (handler_exists) { 611 if (handler_exists) {
612 finder.TrySync();
458 // Found a dart handler for the exception, jump to it. 613 // Found a dart handler for the exception, jump to it.
459 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp, 614 JumpToExceptionHandler(thread, handler_pc, handler_sp, handler_fp,
460 exception, stacktrace); 615 exception, stacktrace);
461 } else { 616 } else {
462 // No dart exception handler found in this invocation sequence, 617 // No dart exception handler found in this invocation sequence,
463 // so we create an unhandled exception object and return to the 618 // so we create an unhandled exception object and return to the
464 // invocation stub so that it returns this unhandled exception 619 // invocation stub so that it returns this unhandled exception
465 // object. The C++ code which invoked this dart sequence can check 620 // object. The C++ code which invoked this dart sequence can check
466 // and do the appropriate thing (rethrow the exception to the 621 // and do the appropriate thing (rethrow the exception to the
467 // dart invocation sequence above it, print diagnostics and terminate 622 // dart invocation sequence above it, print diagnostics and terminate
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 class_name = &Symbols::_CompileTimeError(); 972 class_name = &Symbols::_CompileTimeError();
818 break; 973 break;
819 } 974 }
820 975
821 return DartLibraryCalls::InstanceCreate(library, *class_name, 976 return DartLibraryCalls::InstanceCreate(library, *class_name,
822 *constructor_name, arguments); 977 *constructor_name, arguments);
823 } 978 }
824 979
825 980
826 } // namespace dart 981 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/exceptions.h ('k') | runtime/vm/fixed_cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698