OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "factory.h" | 30 #include "factory.h" |
31 #include "string-stream.h" | 31 #include "string-stream.h" |
32 | 32 |
33 namespace v8 { | 33 namespace v8 { |
34 namespace internal { | 34 namespace internal { |
35 | 35 |
36 static const int kMentionedObjectCacheMaxSize = 256; | 36 static const int kMentionedObjectCacheMaxSize = 256; |
37 static List<HeapObject*, PreallocatedStorage>* debug_object_cache = NULL; | |
38 static Object* current_security_token = NULL; | |
39 | |
40 | 37 |
41 char* HeapStringAllocator::allocate(unsigned bytes) { | 38 char* HeapStringAllocator::allocate(unsigned bytes) { |
42 space_ = NewArray<char>(bytes); | 39 space_ = NewArray<char>(bytes); |
43 return space_; | 40 return space_; |
44 } | 41 } |
45 | 42 |
46 | 43 |
47 NoAllocationStringAllocator::NoAllocationStringAllocator(char* memory, | 44 NoAllocationStringAllocator::NoAllocationStringAllocator(char* memory, |
48 unsigned size) { | 45 unsigned size) { |
49 size_ = size; | 46 size_ = size; |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 void StringStream::PrintObject(Object* o) { | 185 void StringStream::PrintObject(Object* o) { |
189 o->ShortPrint(this); | 186 o->ShortPrint(this); |
190 if (o->IsString()) { | 187 if (o->IsString()) { |
191 if (String::cast(o)->length() <= String::kMaxShortPrintLength) { | 188 if (String::cast(o)->length() <= String::kMaxShortPrintLength) { |
192 return; | 189 return; |
193 } | 190 } |
194 } else if (o->IsNumber() || o->IsOddball()) { | 191 } else if (o->IsNumber() || o->IsOddball()) { |
195 return; | 192 return; |
196 } | 193 } |
197 if (o->IsHeapObject()) { | 194 if (o->IsHeapObject()) { |
| 195 DebugObjectCache* debug_object_cache = Isolate::Current()-> |
| 196 string_stream_debug_object_cache(); |
198 for (int i = 0; i < debug_object_cache->length(); i++) { | 197 for (int i = 0; i < debug_object_cache->length(); i++) { |
199 if ((*debug_object_cache)[i] == o) { | 198 if ((*debug_object_cache)[i] == o) { |
200 Add("#%d#", i); | 199 Add("#%d#", i); |
201 return; | 200 return; |
202 } | 201 } |
203 } | 202 } |
204 if (debug_object_cache->length() < kMentionedObjectCacheMaxSize) { | 203 if (debug_object_cache->length() < kMentionedObjectCacheMaxSize) { |
205 Add("#%d#", debug_object_cache->length()); | 204 Add("#%d#", debug_object_cache->length()); |
206 debug_object_cache->Add(HeapObject::cast(o)); | 205 debug_object_cache->Add(HeapObject::cast(o)); |
207 } else { | 206 } else { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 | 252 |
254 SmartPointer<const char> StringStream::ToCString() const { | 253 SmartPointer<const char> StringStream::ToCString() const { |
255 char* str = NewArray<char>(length_ + 1); | 254 char* str = NewArray<char>(length_ + 1); |
256 memcpy(str, buffer_, length_); | 255 memcpy(str, buffer_, length_); |
257 str[length_] = '\0'; | 256 str[length_] = '\0'; |
258 return SmartPointer<const char>(str); | 257 return SmartPointer<const char>(str); |
259 } | 258 } |
260 | 259 |
261 | 260 |
262 void StringStream::Log() { | 261 void StringStream::Log() { |
263 LOG(StringEvent("StackDump", buffer_)); | 262 LOG(ISOLATE, StringEvent("StackDump", buffer_)); |
264 } | 263 } |
265 | 264 |
266 | 265 |
267 void StringStream::OutputToFile(FILE* out) { | 266 void StringStream::OutputToFile(FILE* out) { |
268 // Dump the output to stdout, but make sure to break it up into | 267 // Dump the output to stdout, but make sure to break it up into |
269 // manageable chunks to avoid losing parts of the output in the OS | 268 // manageable chunks to avoid losing parts of the output in the OS |
270 // printing code. This is a problem on Windows in particular; see | 269 // printing code. This is a problem on Windows in particular; see |
271 // the VPrint() function implementations in platform-win32.cc. | 270 // the VPrint() function implementations in platform-win32.cc. |
272 unsigned position = 0; | 271 unsigned position = 0; |
273 for (unsigned next; (next = position + 2048) < length_; position = next) { | 272 for (unsigned next; (next = position + 2048) < length_; position = next) { |
274 char save = buffer_[next]; | 273 char save = buffer_[next]; |
275 buffer_[next] = '\0'; | 274 buffer_[next] = '\0'; |
276 internal::PrintF(out, "%s", &buffer_[position]); | 275 internal::PrintF(out, "%s", &buffer_[position]); |
277 buffer_[next] = save; | 276 buffer_[next] = save; |
278 } | 277 } |
279 internal::PrintF(out, "%s", &buffer_[position]); | 278 internal::PrintF(out, "%s", &buffer_[position]); |
280 } | 279 } |
281 | 280 |
282 | 281 |
283 Handle<String> StringStream::ToString() { | 282 Handle<String> StringStream::ToString() { |
284 return Factory::NewStringFromUtf8(Vector<const char>(buffer_, length_)); | 283 return FACTORY->NewStringFromUtf8(Vector<const char>(buffer_, length_)); |
285 } | 284 } |
286 | 285 |
287 | 286 |
288 void StringStream::ClearMentionedObjectCache() { | 287 void StringStream::ClearMentionedObjectCache() { |
289 current_security_token = NULL; | 288 Isolate* isolate = Isolate::Current(); |
290 if (debug_object_cache == NULL) { | 289 isolate->set_string_stream_current_security_token(NULL); |
291 debug_object_cache = new List<HeapObject*, PreallocatedStorage>(0); | 290 if (isolate->string_stream_debug_object_cache() == NULL) { |
| 291 isolate->set_string_stream_debug_object_cache( |
| 292 new List<HeapObject*, PreallocatedStorage>(0)); |
292 } | 293 } |
293 debug_object_cache->Clear(); | 294 isolate->string_stream_debug_object_cache()->Clear(); |
294 } | 295 } |
295 | 296 |
296 | 297 |
297 #ifdef DEBUG | 298 #ifdef DEBUG |
298 bool StringStream::IsMentionedObjectCacheClear() { | 299 bool StringStream::IsMentionedObjectCacheClear() { |
299 return (debug_object_cache->length() == 0); | 300 return ( |
| 301 Isolate::Current()->string_stream_debug_object_cache()->length() == 0); |
300 } | 302 } |
301 #endif | 303 #endif |
302 | 304 |
303 | 305 |
304 bool StringStream::Put(String* str) { | 306 bool StringStream::Put(String* str) { |
305 return Put(str, 0, str->length()); | 307 return Put(str, 0, str->length()); |
306 } | 308 } |
307 | 309 |
308 | 310 |
309 bool StringStream::Put(String* str, int start, int end) { | 311 bool StringStream::Put(String* str, int start, int end) { |
(...skipping 21 matching lines...) Expand all Loading... |
331 Add("/* anonymous */"); | 333 Add("/* anonymous */"); |
332 } | 334 } |
333 } else { | 335 } else { |
334 Add("%o", name); | 336 Add("%o", name); |
335 } | 337 } |
336 } | 338 } |
337 | 339 |
338 | 340 |
339 void StringStream::PrintUsingMap(JSObject* js_object) { | 341 void StringStream::PrintUsingMap(JSObject* js_object) { |
340 Map* map = js_object->map(); | 342 Map* map = js_object->map(); |
341 if (!Heap::Contains(map) || | 343 if (!HEAP->Contains(map) || |
342 !map->IsHeapObject() || | 344 !map->IsHeapObject() || |
343 !map->IsMap()) { | 345 !map->IsMap()) { |
344 Add("<Invalid map>\n"); | 346 Add("<Invalid map>\n"); |
345 return; | 347 return; |
346 } | 348 } |
347 DescriptorArray* descs = map->instance_descriptors(); | 349 DescriptorArray* descs = map->instance_descriptors(); |
348 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 350 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
349 switch (descs->GetType(i)) { | 351 switch (descs->GetType(i)) { |
350 case FIELD: { | 352 case FIELD: { |
351 Object* key = descs->GetKey(i); | 353 Object* key = descs->GetKey(i); |
(...skipping 16 matching lines...) Expand all Loading... |
368 } | 370 } |
369 break; | 371 break; |
370 default: | 372 default: |
371 break; | 373 break; |
372 } | 374 } |
373 } | 375 } |
374 } | 376 } |
375 | 377 |
376 | 378 |
377 void StringStream::PrintFixedArray(FixedArray* array, unsigned int limit) { | 379 void StringStream::PrintFixedArray(FixedArray* array, unsigned int limit) { |
| 380 Heap* heap = HEAP; |
378 for (unsigned int i = 0; i < 10 && i < limit; i++) { | 381 for (unsigned int i = 0; i < 10 && i < limit; i++) { |
379 Object* element = array->get(i); | 382 Object* element = array->get(i); |
380 if (element != Heap::the_hole_value()) { | 383 if (element != heap->the_hole_value()) { |
381 for (int len = 1; len < 18; len++) | 384 for (int len = 1; len < 18; len++) |
382 Put(' '); | 385 Put(' '); |
383 Add("%d: %o\n", i, array->get(i)); | 386 Add("%d: %o\n", i, array->get(i)); |
384 } | 387 } |
385 } | 388 } |
386 if (limit >= 10) { | 389 if (limit >= 10) { |
387 Add(" ...\n"); | 390 Add(" ...\n"); |
388 } | 391 } |
389 } | 392 } |
390 | 393 |
(...skipping 14 matching lines...) Expand all Loading... |
405 } | 408 } |
406 Add("\n"); | 409 Add("\n"); |
407 } | 410 } |
408 if (limit >= 10) { | 411 if (limit >= 10) { |
409 Add(" ...\n"); | 412 Add(" ...\n"); |
410 } | 413 } |
411 } | 414 } |
412 | 415 |
413 | 416 |
414 void StringStream::PrintMentionedObjectCache() { | 417 void StringStream::PrintMentionedObjectCache() { |
| 418 DebugObjectCache* debug_object_cache = |
| 419 Isolate::Current()->string_stream_debug_object_cache(); |
415 Add("==== Key ============================================\n\n"); | 420 Add("==== Key ============================================\n\n"); |
416 for (int i = 0; i < debug_object_cache->length(); i++) { | 421 for (int i = 0; i < debug_object_cache->length(); i++) { |
417 HeapObject* printee = (*debug_object_cache)[i]; | 422 HeapObject* printee = (*debug_object_cache)[i]; |
418 Add(" #%d# %p: ", i, printee); | 423 Add(" #%d# %p: ", i, printee); |
419 printee->ShortPrint(this); | 424 printee->ShortPrint(this); |
420 Add("\n"); | 425 Add("\n"); |
421 if (printee->IsJSObject()) { | 426 if (printee->IsJSObject()) { |
422 if (printee->IsJSValue()) { | 427 if (printee->IsJSValue()) { |
423 Add(" value(): %o\n", JSValue::cast(printee)->value()); | 428 Add(" value(): %o\n", JSValue::cast(printee)->value()); |
424 } | 429 } |
(...skipping 12 matching lines...) Expand all Loading... |
437 PrintByteArray(ByteArray::cast(printee)); | 442 PrintByteArray(ByteArray::cast(printee)); |
438 } else if (printee->IsFixedArray()) { | 443 } else if (printee->IsFixedArray()) { |
439 unsigned int limit = FixedArray::cast(printee)->length(); | 444 unsigned int limit = FixedArray::cast(printee)->length(); |
440 PrintFixedArray(FixedArray::cast(printee), limit); | 445 PrintFixedArray(FixedArray::cast(printee), limit); |
441 } | 446 } |
442 } | 447 } |
443 } | 448 } |
444 | 449 |
445 | 450 |
446 void StringStream::PrintSecurityTokenIfChanged(Object* f) { | 451 void StringStream::PrintSecurityTokenIfChanged(Object* f) { |
447 if (!f->IsHeapObject() || !Heap::Contains(HeapObject::cast(f))) { | 452 Isolate* isolate = Isolate::Current(); |
| 453 Heap* heap = isolate->heap(); |
| 454 if (!f->IsHeapObject() || !heap->Contains(HeapObject::cast(f))) { |
448 return; | 455 return; |
449 } | 456 } |
450 Map* map = HeapObject::cast(f)->map(); | 457 Map* map = HeapObject::cast(f)->map(); |
451 if (!map->IsHeapObject() || | 458 if (!map->IsHeapObject() || |
452 !Heap::Contains(map) || | 459 !heap->Contains(map) || |
453 !map->IsMap() || | 460 !map->IsMap() || |
454 !f->IsJSFunction()) { | 461 !f->IsJSFunction()) { |
455 return; | 462 return; |
456 } | 463 } |
457 | 464 |
458 JSFunction* fun = JSFunction::cast(f); | 465 JSFunction* fun = JSFunction::cast(f); |
459 Object* perhaps_context = fun->unchecked_context(); | 466 Object* perhaps_context = fun->unchecked_context(); |
460 if (perhaps_context->IsHeapObject() && | 467 if (perhaps_context->IsHeapObject() && |
461 Heap::Contains(HeapObject::cast(perhaps_context)) && | 468 heap->Contains(HeapObject::cast(perhaps_context)) && |
462 perhaps_context->IsContext()) { | 469 perhaps_context->IsContext()) { |
463 Context* context = fun->context(); | 470 Context* context = fun->context(); |
464 if (!Heap::Contains(context)) { | 471 if (!heap->Contains(context)) { |
465 Add("(Function context is outside heap)\n"); | 472 Add("(Function context is outside heap)\n"); |
466 return; | 473 return; |
467 } | 474 } |
468 Object* token = context->global_context()->security_token(); | 475 Object* token = context->global_context()->security_token(); |
469 if (token != current_security_token) { | 476 if (token != isolate->string_stream_current_security_token()) { |
470 Add("Security context: %o\n", token); | 477 Add("Security context: %o\n", token); |
471 current_security_token = token; | 478 isolate->set_string_stream_current_security_token(token); |
472 } | 479 } |
473 } else { | 480 } else { |
474 Add("(Function context is corrupt)\n"); | 481 Add("(Function context is corrupt)\n"); |
475 } | 482 } |
476 } | 483 } |
477 | 484 |
478 | 485 |
479 void StringStream::PrintFunction(Object* f, Object* receiver, Code** code) { | 486 void StringStream::PrintFunction(Object* f, Object* receiver, Code** code) { |
480 if (f->IsHeapObject() && | 487 if (f->IsHeapObject() && |
481 Heap::Contains(HeapObject::cast(f)) && | 488 HEAP->Contains(HeapObject::cast(f)) && |
482 Heap::Contains(HeapObject::cast(f)->map()) && | 489 HEAP->Contains(HeapObject::cast(f)->map()) && |
483 HeapObject::cast(f)->map()->IsMap()) { | 490 HeapObject::cast(f)->map()->IsMap()) { |
484 if (f->IsJSFunction()) { | 491 if (f->IsJSFunction()) { |
485 JSFunction* fun = JSFunction::cast(f); | 492 JSFunction* fun = JSFunction::cast(f); |
486 // Common case: on-stack function present and resolved. | 493 // Common case: on-stack function present and resolved. |
487 PrintPrototype(fun, receiver); | 494 PrintPrototype(fun, receiver); |
488 *code = fun->code(); | 495 *code = fun->code(); |
489 } else if (f->IsSymbol()) { | 496 } else if (f->IsSymbol()) { |
490 // Unresolved and megamorphic calls: Instead of the function | 497 // Unresolved and megamorphic calls: Instead of the function |
491 // we have the function name on the stack. | 498 // we have the function name on the stack. |
492 PrintName(f); | 499 PrintName(f); |
493 Add("/* unresolved */ "); | 500 Add("/* unresolved */ "); |
494 } else { | 501 } else { |
495 // Unless this is the frame of a built-in function, we should always have | 502 // Unless this is the frame of a built-in function, we should always have |
496 // the callee function or name on the stack. If we don't, we have a | 503 // the callee function or name on the stack. If we don't, we have a |
497 // problem or a change of the stack frame layout. | 504 // problem or a change of the stack frame layout. |
498 Add("%o", f); | 505 Add("%o", f); |
499 Add("/* warning: no JSFunction object or function name found */ "); | 506 Add("/* warning: no JSFunction object or function name found */ "); |
500 } | 507 } |
501 /* } else if (is_trampoline()) { | 508 /* } else if (is_trampoline()) { |
502 Print("trampoline "); | 509 Print("trampoline "); |
503 */ | 510 */ |
504 } else { | 511 } else { |
505 if (!f->IsHeapObject()) { | 512 if (!f->IsHeapObject()) { |
506 Add("/* warning: 'function' was not a heap object */ "); | 513 Add("/* warning: 'function' was not a heap object */ "); |
507 return; | 514 return; |
508 } | 515 } |
509 if (!Heap::Contains(HeapObject::cast(f))) { | 516 if (!HEAP->Contains(HeapObject::cast(f))) { |
510 Add("/* warning: 'function' was not on the heap */ "); | 517 Add("/* warning: 'function' was not on the heap */ "); |
511 return; | 518 return; |
512 } | 519 } |
513 if (!Heap::Contains(HeapObject::cast(f)->map())) { | 520 if (!HEAP->Contains(HeapObject::cast(f)->map())) { |
514 Add("/* warning: function's map was not on the heap */ "); | 521 Add("/* warning: function's map was not on the heap */ "); |
515 return; | 522 return; |
516 } | 523 } |
517 if (!HeapObject::cast(f)->map()->IsMap()) { | 524 if (!HeapObject::cast(f)->map()->IsMap()) { |
518 Add("/* warning: function's map was not a valid map */ "); | 525 Add("/* warning: function's map was not a valid map */ "); |
519 return; | 526 return; |
520 } | 527 } |
521 Add("/* warning: Invalid JSFunction object found */ "); | 528 Add("/* warning: Invalid JSFunction object found */ "); |
522 } | 529 } |
523 } | 530 } |
524 | 531 |
525 | 532 |
526 void StringStream::PrintPrototype(JSFunction* fun, Object* receiver) { | 533 void StringStream::PrintPrototype(JSFunction* fun, Object* receiver) { |
527 Object* name = fun->shared()->name(); | 534 Object* name = fun->shared()->name(); |
528 bool print_name = false; | 535 bool print_name = false; |
529 for (Object* p = receiver; p != Heap::null_value(); p = p->GetPrototype()) { | 536 Heap* heap = HEAP; |
| 537 for (Object* p = receiver; p != heap->null_value(); p = p->GetPrototype()) { |
530 if (p->IsJSObject()) { | 538 if (p->IsJSObject()) { |
531 Object* key = JSObject::cast(p)->SlowReverseLookup(fun); | 539 Object* key = JSObject::cast(p)->SlowReverseLookup(fun); |
532 if (key != Heap::undefined_value()) { | 540 if (key != heap->undefined_value()) { |
533 if (!name->IsString() || | 541 if (!name->IsString() || |
534 !key->IsString() || | 542 !key->IsString() || |
535 !String::cast(name)->Equals(String::cast(key))) { | 543 !String::cast(name)->Equals(String::cast(key))) { |
536 print_name = true; | 544 print_name = true; |
537 } | 545 } |
538 if (name->IsString() && String::cast(name)->length() == 0) { | 546 if (name->IsString() && String::cast(name)->length() == 0) { |
539 print_name = false; | 547 print_name = false; |
540 } | 548 } |
541 name = key; | 549 name = key; |
542 } | 550 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 | 583 |
576 // Only grow once to the maximum allowable size. | 584 // Only grow once to the maximum allowable size. |
577 char* NoAllocationStringAllocator::grow(unsigned* bytes) { | 585 char* NoAllocationStringAllocator::grow(unsigned* bytes) { |
578 ASSERT(size_ >= *bytes); | 586 ASSERT(size_ >= *bytes); |
579 *bytes = size_; | 587 *bytes = size_; |
580 return space_; | 588 return space_; |
581 } | 589 } |
582 | 590 |
583 | 591 |
584 } } // namespace v8::internal | 592 } } // namespace v8::internal |
OLD | NEW |