1// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "disassembler.h"
31#include "disasm.h"
32#include "jsregexp.h"
33
34namespace v8 {
35namespace internal {
36
37#ifdef DEBUG
38
39static const char* TypeToString(InstanceType type);
40
41
42void Object::Print() {
43  if (IsSmi()) {
44    Smi::cast(this)->SmiPrint();
45  } else if (IsFailure()) {
46    Failure::cast(this)->FailurePrint();
47  } else {
48    HeapObject::cast(this)->HeapObjectPrint();
49  }
50  Flush();
51}
52
53
54void Object::PrintLn() {
55  Print();
56  PrintF("\n");
57}
58
59
60void Object::Verify() {
61  if (IsSmi()) {
62    Smi::cast(this)->SmiVerify();
63  } else if (IsFailure()) {
64    Failure::cast(this)->FailureVerify();
65  } else {
66    HeapObject::cast(this)->HeapObjectVerify();
67  }
68}
69
70
71void Object::VerifyPointer(Object* p) {
72  if (p->IsHeapObject()) {
73    HeapObject::VerifyHeapPointer(p);
74  } else {
75    ASSERT(p->IsSmi());
76  }
77}
78
79
80void Smi::SmiVerify() {
81  ASSERT(IsSmi());
82}
83
84
85void Failure::FailureVerify() {
86  ASSERT(IsFailure());
87}
88
89
90void HeapObject::PrintHeader(const char* id) {
91  PrintF("%p: [%s]\n", this, id);
92}
93
94
95void HeapObject::HeapObjectPrint() {
96  InstanceType instance_type = map()->instance_type();
97
98  HandleScope scope;
99  if (instance_type < FIRST_NONSTRING_TYPE) {
100    String::cast(this)->StringPrint();
101    return;
102  }
103
104  switch (instance_type) {
105    case MAP_TYPE:
106      Map::cast(this)->MapPrint();
107      break;
108    case HEAP_NUMBER_TYPE:
109      HeapNumber::cast(this)->HeapNumberPrint();
110      break;
111    case FIXED_ARRAY_TYPE:
112      FixedArray::cast(this)->FixedArrayPrint();
113      break;
114    case BYTE_ARRAY_TYPE:
115      ByteArray::cast(this)->ByteArrayPrint();
116      break;
117    case PIXEL_ARRAY_TYPE:
118      PixelArray::cast(this)->PixelArrayPrint();
119      break;
120    case EXTERNAL_BYTE_ARRAY_TYPE:
121      ExternalByteArray::cast(this)->ExternalByteArrayPrint();
122      break;
123    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
124      ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayPrint();
125      break;
126    case EXTERNAL_SHORT_ARRAY_TYPE:
127      ExternalShortArray::cast(this)->ExternalShortArrayPrint();
128      break;
129    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
130      ExternalUnsignedShortArray::cast(this)->ExternalUnsignedShortArrayPrint();
131      break;
132    case EXTERNAL_INT_ARRAY_TYPE:
133      ExternalIntArray::cast(this)->ExternalIntArrayPrint();
134      break;
135    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
136      ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayPrint();
137      break;
138    case EXTERNAL_FLOAT_ARRAY_TYPE:
139      ExternalFloatArray::cast(this)->ExternalFloatArrayPrint();
140      break;
141    case FILLER_TYPE:
142      PrintF("filler");
143      break;
144    case JS_OBJECT_TYPE:  // fall through
145    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
146    case JS_ARRAY_TYPE:
147    case JS_REGEXP_TYPE:
148      JSObject::cast(this)->JSObjectPrint();
149      break;
150    case ODDBALL_TYPE:
151      Oddball::cast(this)->to_string()->Print();
152      break;
153    case JS_FUNCTION_TYPE:
154      JSFunction::cast(this)->JSFunctionPrint();
155      break;
156    case JS_GLOBAL_PROXY_TYPE:
157      JSGlobalProxy::cast(this)->JSGlobalProxyPrint();
158      break;
159    case JS_GLOBAL_OBJECT_TYPE:
160      JSGlobalObject::cast(this)->JSGlobalObjectPrint();
161      break;
162    case JS_BUILTINS_OBJECT_TYPE:
163      JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint();
164      break;
165    case JS_VALUE_TYPE:
166      PrintF("Value wrapper around:");
167      JSValue::cast(this)->value()->Print();
168      break;
169    case CODE_TYPE:
170      Code::cast(this)->CodePrint();
171      break;
172    case PROXY_TYPE:
173      Proxy::cast(this)->ProxyPrint();
174      break;
175    case SHARED_FUNCTION_INFO_TYPE:
176      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint();
177      break;
178    case JS_GLOBAL_PROPERTY_CELL_TYPE:
179      JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellPrint();
180      break;
181#define MAKE_STRUCT_CASE(NAME, Name, name) \
182  case NAME##_TYPE:                        \
183    Name::cast(this)->Name##Print();       \
184    break;
185  STRUCT_LIST(MAKE_STRUCT_CASE)
186#undef MAKE_STRUCT_CASE
187
188    default:
189      PrintF("UNKNOWN TYPE %d", map()->instance_type());
190      UNREACHABLE();
191      break;
192  }
193}
194
195
196void HeapObject::HeapObjectVerify() {
197  InstanceType instance_type = map()->instance_type();
198
199  if (instance_type < FIRST_NONSTRING_TYPE) {
200    String::cast(this)->StringVerify();
201    return;
202  }
203
204  switch (instance_type) {
205    case MAP_TYPE:
206      Map::cast(this)->MapVerify();
207      break;
208    case HEAP_NUMBER_TYPE:
209      HeapNumber::cast(this)->HeapNumberVerify();
210      break;
211    case FIXED_ARRAY_TYPE:
212      FixedArray::cast(this)->FixedArrayVerify();
213      break;
214    case BYTE_ARRAY_TYPE:
215      ByteArray::cast(this)->ByteArrayVerify();
216      break;
217    case PIXEL_ARRAY_TYPE:
218      PixelArray::cast(this)->PixelArrayVerify();
219      break;
220    case EXTERNAL_BYTE_ARRAY_TYPE:
221      ExternalByteArray::cast(this)->ExternalByteArrayVerify();
222      break;
223    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
224      ExternalUnsignedByteArray::cast(this)->ExternalUnsignedByteArrayVerify();
225      break;
226    case EXTERNAL_SHORT_ARRAY_TYPE:
227      ExternalShortArray::cast(this)->ExternalShortArrayVerify();
228      break;
229    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
230      ExternalUnsignedShortArray::cast(this)->
231          ExternalUnsignedShortArrayVerify();
232      break;
233    case EXTERNAL_INT_ARRAY_TYPE:
234      ExternalIntArray::cast(this)->ExternalIntArrayVerify();
235      break;
236    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
237      ExternalUnsignedIntArray::cast(this)->ExternalUnsignedIntArrayVerify();
238      break;
239    case EXTERNAL_FLOAT_ARRAY_TYPE:
240      ExternalFloatArray::cast(this)->ExternalFloatArrayVerify();
241      break;
242    case CODE_TYPE:
243      Code::cast(this)->CodeVerify();
244      break;
245    case ODDBALL_TYPE:
246      Oddball::cast(this)->OddballVerify();
247      break;
248    case JS_OBJECT_TYPE:
249    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
250      JSObject::cast(this)->JSObjectVerify();
251      break;
252    case JS_VALUE_TYPE:
253      JSValue::cast(this)->JSValueVerify();
254      break;
255    case JS_FUNCTION_TYPE:
256      JSFunction::cast(this)->JSFunctionVerify();
257      break;
258    case JS_GLOBAL_PROXY_TYPE:
259      JSGlobalProxy::cast(this)->JSGlobalProxyVerify();
260      break;
261    case JS_GLOBAL_OBJECT_TYPE:
262      JSGlobalObject::cast(this)->JSGlobalObjectVerify();
263      break;
264    case JS_BUILTINS_OBJECT_TYPE:
265      JSBuiltinsObject::cast(this)->JSBuiltinsObjectVerify();
266      break;
267    case JS_GLOBAL_PROPERTY_CELL_TYPE:
268      JSGlobalPropertyCell::cast(this)->JSGlobalPropertyCellVerify();
269      break;
270    case JS_ARRAY_TYPE:
271      JSArray::cast(this)->JSArrayVerify();
272      break;
273    case JS_REGEXP_TYPE:
274      JSRegExp::cast(this)->JSRegExpVerify();
275      break;
276    case FILLER_TYPE:
277      break;
278    case PROXY_TYPE:
279      Proxy::cast(this)->ProxyVerify();
280      break;
281    case SHARED_FUNCTION_INFO_TYPE:
282      SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
283      break;
284
285#define MAKE_STRUCT_CASE(NAME, Name, name) \
286  case NAME##_TYPE:                        \
287    Name::cast(this)->Name##Verify();      \
288    break;
289    STRUCT_LIST(MAKE_STRUCT_CASE)
290#undef MAKE_STRUCT_CASE
291
292    default:
293      UNREACHABLE();
294      break;
295  }
296}
297
298
299void HeapObject::VerifyHeapPointer(Object* p) {
300  ASSERT(p->IsHeapObject());
301  ASSERT(Heap::Contains(HeapObject::cast(p)));
302}
303
304
305void HeapNumber::HeapNumberVerify() {
306  ASSERT(IsHeapNumber());
307}
308
309
310void ByteArray::ByteArrayPrint() {
311  PrintF("byte array, data starts at %p", GetDataStartAddress());
312}
313
314
315void PixelArray::PixelArrayPrint() {
316  PrintF("pixel array");
317}
318
319
320void ExternalByteArray::ExternalByteArrayPrint() {
321  PrintF("external byte array");
322}
323
324
325void ExternalUnsignedByteArray::ExternalUnsignedByteArrayPrint() {
326  PrintF("external unsigned byte array");
327}
328
329
330void ExternalShortArray::ExternalShortArrayPrint() {
331  PrintF("external short array");
332}
333
334
335void ExternalUnsignedShortArray::ExternalUnsignedShortArrayPrint() {
336  PrintF("external unsigned short array");
337}
338
339
340void ExternalIntArray::ExternalIntArrayPrint() {
341  PrintF("external int array");
342}
343
344
345void ExternalUnsignedIntArray::ExternalUnsignedIntArrayPrint() {
346  PrintF("external unsigned int array");
347}
348
349
350void ExternalFloatArray::ExternalFloatArrayPrint() {
351  PrintF("external float array");
352}
353
354
355void ByteArray::ByteArrayVerify() {
356  ASSERT(IsByteArray());
357}
358
359
360void PixelArray::PixelArrayVerify() {
361  ASSERT(IsPixelArray());
362}
363
364
365void ExternalByteArray::ExternalByteArrayVerify() {
366  ASSERT(IsExternalByteArray());
367}
368
369
370void ExternalUnsignedByteArray::ExternalUnsignedByteArrayVerify() {
371  ASSERT(IsExternalUnsignedByteArray());
372}
373
374
375void ExternalShortArray::ExternalShortArrayVerify() {
376  ASSERT(IsExternalShortArray());
377}
378
379
380void ExternalUnsignedShortArray::ExternalUnsignedShortArrayVerify() {
381  ASSERT(IsExternalUnsignedShortArray());
382}
383
384
385void ExternalIntArray::ExternalIntArrayVerify() {
386  ASSERT(IsExternalIntArray());
387}
388
389
390void ExternalUnsignedIntArray::ExternalUnsignedIntArrayVerify() {
391  ASSERT(IsExternalUnsignedIntArray());
392}
393
394
395void ExternalFloatArray::ExternalFloatArrayVerify() {
396  ASSERT(IsExternalFloatArray());
397}
398
399
400void JSObject::PrintProperties() {
401  if (HasFastProperties()) {
402    DescriptorArray* descs = map()->instance_descriptors();
403    for (int i = 0; i < descs->number_of_descriptors(); i++) {
404      PrintF("   ");
405      descs->GetKey(i)->StringPrint();
406      PrintF(": ");
407      switch (descs->GetType(i)) {
408        case FIELD: {
409          int index = descs->GetFieldIndex(i);
410          FastPropertyAt(index)->ShortPrint();
411          PrintF(" (field at offset %d)\n", index);
412          break;
413        }
414        case CONSTANT_FUNCTION:
415          descs->GetConstantFunction(i)->ShortPrint();
416          PrintF(" (constant function)\n");
417          break;
418        case CALLBACKS:
419          descs->GetCallbacksObject(i)->ShortPrint();
420          PrintF(" (callback)\n");
421          break;
422        case MAP_TRANSITION:
423          PrintF(" (map transition)\n");
424          break;
425        case CONSTANT_TRANSITION:
426          PrintF(" (constant transition)\n");
427          break;
428        case NULL_DESCRIPTOR:
429          PrintF(" (null descriptor)\n");
430          break;
431        default:
432          UNREACHABLE();
433          break;
434      }
435    }
436  } else {
437    property_dictionary()->Print();
438  }
439}
440
441
442void JSObject::PrintElements() {
443  switch (GetElementsKind()) {
444    case FAST_ELEMENTS: {
445      // Print in array notation for non-sparse arrays.
446      FixedArray* p = FixedArray::cast(elements());
447      for (int i = 0; i < p->length(); i++) {
448        PrintF("   %d: ", i);
449        p->get(i)->ShortPrint();
450        PrintF("\n");
451      }
452      break;
453    }
454    case PIXEL_ELEMENTS: {
455      PixelArray* p = PixelArray::cast(elements());
456      for (int i = 0; i < p->length(); i++) {
457        PrintF("   %d: %d\n", i, p->get(i));
458      }
459      break;
460    }
461    case EXTERNAL_BYTE_ELEMENTS: {
462      ExternalByteArray* p = ExternalByteArray::cast(elements());
463      for (int i = 0; i < p->length(); i++) {
464        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
465      }
466      break;
467    }
468    case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: {
469      ExternalUnsignedByteArray* p =
470          ExternalUnsignedByteArray::cast(elements());
471      for (int i = 0; i < p->length(); i++) {
472        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
473      }
474      break;
475    }
476    case EXTERNAL_SHORT_ELEMENTS: {
477      ExternalShortArray* p = ExternalShortArray::cast(elements());
478      for (int i = 0; i < p->length(); i++) {
479        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
480      }
481      break;
482    }
483    case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: {
484      ExternalUnsignedShortArray* p =
485          ExternalUnsignedShortArray::cast(elements());
486      for (int i = 0; i < p->length(); i++) {
487        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
488      }
489      break;
490    }
491    case EXTERNAL_INT_ELEMENTS: {
492      ExternalIntArray* p = ExternalIntArray::cast(elements());
493      for (int i = 0; i < p->length(); i++) {
494        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
495      }
496      break;
497    }
498    case EXTERNAL_UNSIGNED_INT_ELEMENTS: {
499      ExternalUnsignedIntArray* p =
500          ExternalUnsignedIntArray::cast(elements());
501      for (int i = 0; i < p->length(); i++) {
502        PrintF("   %d: %d\n", i, static_cast<int>(p->get(i)));
503      }
504      break;
505    }
506    case EXTERNAL_FLOAT_ELEMENTS: {
507      ExternalFloatArray* p = ExternalFloatArray::cast(elements());
508      for (int i = 0; i < p->length(); i++) {
509        PrintF("   %d: %f\n", i, p->get(i));
510      }
511      break;
512    }
513    case DICTIONARY_ELEMENTS:
514      elements()->Print();
515      break;
516    default:
517      UNREACHABLE();
518      break;
519  }
520}
521
522
523void JSObject::JSObjectPrint() {
524  PrintF("%p: [JSObject]\n", this);
525  PrintF(" - map = %p\n", map());
526  PrintF(" - prototype = %p\n", GetPrototype());
527  PrintF(" {\n");
528  PrintProperties();
529  PrintElements();
530  PrintF(" }\n");
531}
532
533
534void JSObject::JSObjectVerify() {
535  VerifyHeapPointer(properties());
536  VerifyHeapPointer(elements());
537  if (HasFastProperties()) {
538    CHECK_EQ(map()->unused_property_fields(),
539             (map()->inobject_properties() + properties()->length() -
540              map()->NextFreePropertyIndex()));
541  }
542}
543
544
545static const char* TypeToString(InstanceType type) {
546  switch (type) {
547    case INVALID_TYPE: return "INVALID";
548    case MAP_TYPE: return "MAP";
549    case HEAP_NUMBER_TYPE: return "HEAP_NUMBER";
550    case SYMBOL_TYPE: return "SYMBOL";
551    case ASCII_SYMBOL_TYPE: return "ASCII_SYMBOL";
552    case CONS_SYMBOL_TYPE: return "CONS_SYMBOL";
553    case CONS_ASCII_SYMBOL_TYPE: return "CONS_ASCII_SYMBOL";
554    case EXTERNAL_ASCII_SYMBOL_TYPE:
555    case EXTERNAL_SYMBOL_TYPE: return "EXTERNAL_SYMBOL";
556    case ASCII_STRING_TYPE: return "ASCII_STRING";
557    case STRING_TYPE: return "TWO_BYTE_STRING";
558    case CONS_STRING_TYPE:
559    case CONS_ASCII_STRING_TYPE: return "CONS_STRING";
560    case EXTERNAL_ASCII_STRING_TYPE:
561    case EXTERNAL_STRING_TYPE: return "EXTERNAL_STRING";
562    case FIXED_ARRAY_TYPE: return "FIXED_ARRAY";
563    case BYTE_ARRAY_TYPE: return "BYTE_ARRAY";
564    case PIXEL_ARRAY_TYPE: return "PIXEL_ARRAY";
565    case EXTERNAL_BYTE_ARRAY_TYPE: return "EXTERNAL_BYTE_ARRAY";
566    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
567      return "EXTERNAL_UNSIGNED_BYTE_ARRAY";
568    case EXTERNAL_SHORT_ARRAY_TYPE: return "EXTERNAL_SHORT_ARRAY";
569    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
570      return "EXTERNAL_UNSIGNED_SHORT_ARRAY";
571    case EXTERNAL_INT_ARRAY_TYPE: return "EXTERNAL_INT_ARRAY";
572    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
573      return "EXTERNAL_UNSIGNED_INT_ARRAY";
574    case EXTERNAL_FLOAT_ARRAY_TYPE: return "EXTERNAL_FLOAT_ARRAY";
575    case FILLER_TYPE: return "FILLER";
576    case JS_OBJECT_TYPE: return "JS_OBJECT";
577    case JS_CONTEXT_EXTENSION_OBJECT_TYPE: return "JS_CONTEXT_EXTENSION_OBJECT";
578    case ODDBALL_TYPE: return "ODDBALL";
579    case JS_GLOBAL_PROPERTY_CELL_TYPE: return "JS_GLOBAL_PROPERTY_CELL";
580    case SHARED_FUNCTION_INFO_TYPE: return "SHARED_FUNCTION_INFO";
581    case JS_FUNCTION_TYPE: return "JS_FUNCTION";
582    case CODE_TYPE: return "CODE";
583    case JS_ARRAY_TYPE: return "JS_ARRAY";
584    case JS_REGEXP_TYPE: return "JS_REGEXP";
585    case JS_VALUE_TYPE: return "JS_VALUE";
586    case JS_GLOBAL_OBJECT_TYPE: return "JS_GLOBAL_OBJECT";
587    case JS_BUILTINS_OBJECT_TYPE: return "JS_BUILTINS_OBJECT";
588    case JS_GLOBAL_PROXY_TYPE: return "JS_GLOBAL_PROXY";
589    case PROXY_TYPE: return "PROXY";
590#define MAKE_STRUCT_CASE(NAME, Name, name) case NAME##_TYPE: return #NAME;
591  STRUCT_LIST(MAKE_STRUCT_CASE)
592#undef MAKE_STRUCT_CASE
593  }
594  return "UNKNOWN";
595}
596
597
598void Map::MapPrint() {
599  HeapObject::PrintHeader("Map");
600  PrintF(" - type: %s\n", TypeToString(instance_type()));
601  PrintF(" - instance size: %d\n", instance_size());
602  PrintF(" - inobject properties: %d\n", inobject_properties());
603  PrintF(" - pre-allocated property fields: %d\n",
604      pre_allocated_property_fields());
605  PrintF(" - unused property fields: %d\n", unused_property_fields());
606  if (is_hidden_prototype()) {
607    PrintF(" - hidden_prototype\n");
608  }
609  if (has_named_interceptor()) {
610    PrintF(" - named_interceptor\n");
611  }
612  if (has_indexed_interceptor()) {
613    PrintF(" - indexed_interceptor\n");
614  }
615  if (is_undetectable()) {
616    PrintF(" - undetectable\n");
617  }
618  if (has_instance_call_handler()) {
619    PrintF(" - instance_call_handler\n");
620  }
621  if (is_access_check_needed()) {
622    PrintF(" - access_check_needed\n");
623  }
624  PrintF(" - instance descriptors: ");
625  instance_descriptors()->ShortPrint();
626  PrintF("\n - prototype: ");
627  prototype()->ShortPrint();
628  PrintF("\n - constructor: ");
629  constructor()->ShortPrint();
630  PrintF("\n");
631}
632
633
634void Map::MapVerify() {
635  ASSERT(!Heap::InNewSpace(this));
636  ASSERT(FIRST_TYPE <= instance_type() && instance_type() <= LAST_TYPE);
637  ASSERT(kPointerSize <= instance_size()
638         && instance_size() < Heap::Capacity());
639  VerifyHeapPointer(prototype());
640  VerifyHeapPointer(instance_descriptors());
641}
642
643
644void FixedArray::FixedArrayPrint() {
645  HeapObject::PrintHeader("FixedArray");
646  PrintF(" - length: %d", length());
647  for (int i = 0; i < length(); i++) {
648    PrintF("\n  [%d]: ", i);
649    get(i)->ShortPrint();
650  }
651  PrintF("\n");
652}
653
654
655void FixedArray::FixedArrayVerify() {
656  for (int i = 0; i < length(); i++) {
657    Object* e = get(i);
658    if (e->IsHeapObject()) {
659      VerifyHeapPointer(e);
660    } else {
661      e->Verify();
662    }
663  }
664}
665
666
667void JSValue::JSValuePrint() {
668  HeapObject::PrintHeader("ValueObject");
669  value()->Print();
670}
671
672
673void JSValue::JSValueVerify() {
674  Object* v = value();
675  if (v->IsHeapObject()) {
676    VerifyHeapPointer(v);
677  }
678}
679
680
681void String::StringPrint() {
682  if (StringShape(this).IsSymbol()) {
683    PrintF("#");
684  } else if (StringShape(this).IsCons()) {
685    PrintF("c\"");
686  } else {
687    PrintF("\"");
688  }
689
690  for (int i = 0; i < length(); i++) {
691    PrintF("%c", Get(i));
692  }
693
694  if (!StringShape(this).IsSymbol()) PrintF("\"");
695}
696
697
698void String::StringVerify() {
699  CHECK(IsString());
700  CHECK(length() >= 0 && length() <= Smi::kMaxValue);
701  if (IsSymbol()) {
702    CHECK(!Heap::InNewSpace(this));
703  }
704}
705
706
707void JSFunction::JSFunctionPrint() {
708  HeapObject::PrintHeader("Function");
709  PrintF(" - map = 0x%p\n", map());
710  PrintF(" - is boilerplate: %s\n", IsBoilerplate() ? "yes" : "no");
711  PrintF(" - initial_map = ");
712  if (has_initial_map()) {
713    initial_map()->ShortPrint();
714  }
715  PrintF("\n - shared_info = ");
716  shared()->ShortPrint();
717  PrintF("\n   - name = ");
718  shared()->name()->Print();
719  PrintF("\n - context = ");
720  unchecked_context()->ShortPrint();
721  PrintF("\n - code = ");
722  code()->ShortPrint();
723  PrintF("\n");
724
725  PrintProperties();
726  PrintElements();
727
728  PrintF("\n");
729}
730
731
732void JSFunction::JSFunctionVerify() {
733  CHECK(IsJSFunction());
734  VerifyObjectField(kPrototypeOrInitialMapOffset);
735}
736
737
738void SharedFunctionInfo::SharedFunctionInfoPrint() {
739  HeapObject::PrintHeader("SharedFunctionInfo");
740  PrintF(" - name: ");
741  name()->ShortPrint();
742  PrintF("\n - expected_nof_properties: %d", expected_nof_properties());
743  PrintF("\n - instance class name = ");
744  instance_class_name()->Print();
745  PrintF("\n - code = ");
746  code()->ShortPrint();
747  PrintF("\n - source code = ");
748  GetSourceCode()->ShortPrint();
749  // Script files are often large, hard to read.
750  // PrintF("\n - script =");
751  // script()->Print();
752  PrintF("\n - function token position = %d", function_token_position());
753  PrintF("\n - start position = %d", start_position());
754  PrintF("\n - end position = %d", end_position());
755  PrintF("\n - is expression = %d", is_expression());
756  PrintF("\n - debug info = ");
757  debug_info()->ShortPrint();
758  PrintF("\n - length = %d", length());
759  PrintF("\n - has_only_simple_this_property_assignments = %d",
760         has_only_simple_this_property_assignments());
761  PrintF("\n - this_property_assignments = ");
762  this_property_assignments()->ShortPrint();
763  PrintF("\n");
764}
765
766void SharedFunctionInfo::SharedFunctionInfoVerify() {
767  CHECK(IsSharedFunctionInfo());
768  VerifyObjectField(kNameOffset);
769  VerifyObjectField(kCodeOffset);
770  VerifyObjectField(kInstanceClassNameOffset);
771  VerifyObjectField(kExternalReferenceDataOffset);
772  VerifyObjectField(kScriptOffset);
773  VerifyObjectField(kDebugInfoOffset);
774}
775
776
777void JSGlobalProxy::JSGlobalProxyPrint() {
778  PrintF("global_proxy");
779  JSObjectPrint();
780  PrintF("context : ");
781  context()->ShortPrint();
782  PrintF("\n");
783}
784
785
786void JSGlobalProxy::JSGlobalProxyVerify() {
787  CHECK(IsJSGlobalProxy());
788  JSObjectVerify();
789  VerifyObjectField(JSGlobalProxy::kContextOffset);
790  // Make sure that this object has no properties, elements.
791  CHECK_EQ(0, properties()->length());
792  CHECK_EQ(0, elements()->length());
793}
794
795
796void JSGlobalObject::JSGlobalObjectPrint() {
797  PrintF("global ");
798  JSObjectPrint();
799  PrintF("global context : ");
800  global_context()->ShortPrint();
801  PrintF("\n");
802}
803
804
805void JSGlobalObject::JSGlobalObjectVerify() {
806  CHECK(IsJSGlobalObject());
807  JSObjectVerify();
808  for (int i = GlobalObject::kBuiltinsOffset;
809       i < JSGlobalObject::kSize;
810       i += kPointerSize) {
811    VerifyObjectField(i);
812  }
813}
814
815
816void JSBuiltinsObject::JSBuiltinsObjectPrint() {
817  PrintF("builtins ");
818  JSObjectPrint();
819}
820
821
822void JSBuiltinsObject::JSBuiltinsObjectVerify() {
823  CHECK(IsJSBuiltinsObject());
824  JSObjectVerify();
825  for (int i = GlobalObject::kBuiltinsOffset;
826       i < JSBuiltinsObject::kSize;
827       i += kPointerSize) {
828    VerifyObjectField(i);
829  }
830}
831
832
833void Oddball::OddballVerify() {
834  CHECK(IsOddball());
835  VerifyHeapPointer(to_string());
836  Object* number = to_number();
837  if (number->IsHeapObject()) {
838    ASSERT(number == Heap::nan_value());
839  } else {
840    ASSERT(number->IsSmi());
841    int value = Smi::cast(number)->value();
842    ASSERT(value == 0 || value == 1 || value == -1 ||
843           value == -2 || value == -3);
844  }
845}
846
847
848void JSGlobalPropertyCell::JSGlobalPropertyCellVerify() {
849  CHECK(IsJSGlobalPropertyCell());
850  VerifyObjectField(kValueOffset);
851}
852
853
854void JSGlobalPropertyCell::JSGlobalPropertyCellPrint() {
855  HeapObject::PrintHeader("JSGlobalPropertyCell");
856}
857
858
859void Code::CodePrint() {
860  HeapObject::PrintHeader("Code");
861#ifdef ENABLE_DISASSEMBLER
862  Disassemble(NULL);
863#endif
864}
865
866
867void Code::CodeVerify() {
868  CHECK(IsAligned(reinterpret_cast<intptr_t>(instruction_start()),
869                  static_cast<intptr_t>(kCodeAlignment)));
870  Address last_gc_pc = NULL;
871  for (RelocIterator it(this); !it.done(); it.next()) {
872    it.rinfo()->Verify();
873    // Ensure that GC will not iterate twice over the same pointer.
874    if (RelocInfo::IsGCRelocMode(it.rinfo()->rmode())) {
875      CHECK(it.rinfo()->pc() != last_gc_pc);
876      last_gc_pc = it.rinfo()->pc();
877    }
878  }
879}
880
881
882void JSArray::JSArrayVerify() {
883  JSObjectVerify();
884  ASSERT(length()->IsNumber() || length()->IsUndefined());
885  ASSERT(elements()->IsUndefined() || elements()->IsFixedArray());
886}
887
888
889void JSRegExp::JSRegExpVerify() {
890  JSObjectVerify();
891  ASSERT(data()->IsUndefined() || data()->IsFixedArray());
892  switch (TypeTag()) {
893    case JSRegExp::ATOM: {
894      FixedArray* arr = FixedArray::cast(data());
895      ASSERT(arr->get(JSRegExp::kAtomPatternIndex)->IsString());
896      break;
897    }
898    case JSRegExp::IRREGEXP: {
899      bool is_native = RegExpImpl::UsesNativeRegExp();
900
901      FixedArray* arr = FixedArray::cast(data());
902      Object* ascii_data = arr->get(JSRegExp::kIrregexpASCIICodeIndex);
903      // TheHole : Not compiled yet.
904      // JSObject: Compilation error.
905      // Code/ByteArray: Compiled code.
906      ASSERT(ascii_data->IsTheHole() || ascii_data->IsJSObject() ||
907          (is_native ? ascii_data->IsCode() : ascii_data->IsByteArray()));
908      Object* uc16_data = arr->get(JSRegExp::kIrregexpUC16CodeIndex);
909      ASSERT(uc16_data->IsTheHole() || ascii_data->IsJSObject() ||
910          (is_native ? uc16_data->IsCode() : uc16_data->IsByteArray()));
911      ASSERT(arr->get(JSRegExp::kIrregexpCaptureCountIndex)->IsSmi());
912      ASSERT(arr->get(JSRegExp::kIrregexpMaxRegisterCountIndex)->IsSmi());
913      break;
914    }
915    default:
916      ASSERT_EQ(JSRegExp::NOT_COMPILED, TypeTag());
917      ASSERT(data()->IsUndefined());
918      break;
919  }
920}
921
922
923void Proxy::ProxyPrint() {
924  PrintF("proxy to %p", proxy());
925}
926
927
928void Proxy::ProxyVerify() {
929  ASSERT(IsProxy());
930}
931
932
933void AccessorInfo::AccessorInfoVerify() {
934  CHECK(IsAccessorInfo());
935  VerifyPointer(getter());
936  VerifyPointer(setter());
937  VerifyPointer(name());
938  VerifyPointer(data());
939  VerifyPointer(flag());
940  VerifyPointer(load_stub_cache());
941}
942
943void AccessorInfo::AccessorInfoPrint() {
944  HeapObject::PrintHeader("AccessorInfo");
945  PrintF("\n - getter: ");
946  getter()->ShortPrint();
947  PrintF("\n - setter: ");
948  setter()->ShortPrint();
949  PrintF("\n - name: ");
950  name()->ShortPrint();
951  PrintF("\n - data: ");
952  data()->ShortPrint();
953  PrintF("\n - flag: ");
954  flag()->ShortPrint();
955}
956
957void AccessCheckInfo::AccessCheckInfoVerify() {
958  CHECK(IsAccessCheckInfo());
959  VerifyPointer(named_callback());
960  VerifyPointer(indexed_callback());
961  VerifyPointer(data());
962}
963
964void AccessCheckInfo::AccessCheckInfoPrint() {
965  HeapObject::PrintHeader("AccessCheckInfo");
966  PrintF("\n - named_callback: ");
967  named_callback()->ShortPrint();
968  PrintF("\n - indexed_callback: ");
969  indexed_callback()->ShortPrint();
970  PrintF("\n - data: ");
971  data()->ShortPrint();
972}
973
974void InterceptorInfo::InterceptorInfoVerify() {
975  CHECK(IsInterceptorInfo());
976  VerifyPointer(getter());
977  VerifyPointer(setter());
978  VerifyPointer(query());
979  VerifyPointer(deleter());
980  VerifyPointer(enumerator());
981  VerifyPointer(data());
982}
983
984void InterceptorInfo::InterceptorInfoPrint() {
985  HeapObject::PrintHeader("InterceptorInfo");
986  PrintF("\n - getter: ");
987  getter()->ShortPrint();
988  PrintF("\n - setter: ");
989  setter()->ShortPrint();
990  PrintF("\n - query: ");
991  query()->ShortPrint();
992  PrintF("\n - deleter: ");
993  deleter()->ShortPrint();
994  PrintF("\n - enumerator: ");
995  enumerator()->ShortPrint();
996  PrintF("\n - data: ");
997  data()->ShortPrint();
998}
999
1000void CallHandlerInfo::CallHandlerInfoVerify() {
1001  CHECK(IsCallHandlerInfo());
1002  VerifyPointer(callback());
1003  VerifyPointer(data());
1004}
1005
1006void CallHandlerInfo::CallHandlerInfoPrint() {
1007  HeapObject::PrintHeader("CallHandlerInfo");
1008  PrintF("\n - callback: ");
1009  callback()->ShortPrint();
1010  PrintF("\n - data: ");
1011  data()->ShortPrint();
1012}
1013
1014void TemplateInfo::TemplateInfoVerify() {
1015  VerifyPointer(tag());
1016  VerifyPointer(property_list());
1017}
1018
1019void FunctionTemplateInfo::FunctionTemplateInfoVerify() {
1020  CHECK(IsFunctionTemplateInfo());
1021  TemplateInfoVerify();
1022  VerifyPointer(serial_number());
1023  VerifyPointer(call_code());
1024  VerifyPointer(property_accessors());
1025  VerifyPointer(prototype_template());
1026  VerifyPointer(parent_template());
1027  VerifyPointer(named_property_handler());
1028  VerifyPointer(indexed_property_handler());
1029  VerifyPointer(instance_template());
1030  VerifyPointer(signature());
1031  VerifyPointer(access_check_info());
1032}
1033
1034void FunctionTemplateInfo::FunctionTemplateInfoPrint() {
1035  HeapObject::PrintHeader("FunctionTemplateInfo");
1036  PrintF("\n - class name: ");
1037  class_name()->ShortPrint();
1038  PrintF("\n - tag: ");
1039  tag()->ShortPrint();
1040  PrintF("\n - property_list: ");
1041  property_list()->ShortPrint();
1042  PrintF("\n - serial_number: ");
1043  serial_number()->ShortPrint();
1044  PrintF("\n - call_code: ");
1045  call_code()->ShortPrint();
1046  PrintF("\n - property_accessors: ");
1047  property_accessors()->ShortPrint();
1048  PrintF("\n - prototype_template: ");
1049  prototype_template()->ShortPrint();
1050  PrintF("\n - parent_template: ");
1051  parent_template()->ShortPrint();
1052  PrintF("\n - named_property_handler: ");
1053  named_property_handler()->ShortPrint();
1054  PrintF("\n - indexed_property_handler: ");
1055  indexed_property_handler()->ShortPrint();
1056  PrintF("\n - instance_template: ");
1057  instance_template()->ShortPrint();
1058  PrintF("\n - signature: ");
1059  signature()->ShortPrint();
1060  PrintF("\n - access_check_info: ");
1061  access_check_info()->ShortPrint();
1062  PrintF("\n - hidden_prototype: %s", hidden_prototype() ? "true" : "false");
1063  PrintF("\n - undetectable: %s", undetectable() ? "true" : "false");
1064  PrintF("\n - need_access_check: %s", needs_access_check() ? "true" : "false");
1065}
1066
1067void ObjectTemplateInfo::ObjectTemplateInfoVerify() {
1068  CHECK(IsObjectTemplateInfo());
1069  TemplateInfoVerify();
1070  VerifyPointer(constructor());
1071  VerifyPointer(internal_field_count());
1072}
1073
1074void ObjectTemplateInfo::ObjectTemplateInfoPrint() {
1075  HeapObject::PrintHeader("ObjectTemplateInfo");
1076  PrintF("\n - constructor: ");
1077  constructor()->ShortPrint();
1078  PrintF("\n - internal_field_count: ");
1079  internal_field_count()->ShortPrint();
1080}
1081
1082void SignatureInfo::SignatureInfoVerify() {
1083  CHECK(IsSignatureInfo());
1084  VerifyPointer(receiver());
1085  VerifyPointer(args());
1086}
1087
1088void SignatureInfo::SignatureInfoPrint() {
1089  HeapObject::PrintHeader("SignatureInfo");
1090  PrintF("\n - receiver: ");
1091  receiver()->ShortPrint();
1092  PrintF("\n - args: ");
1093  args()->ShortPrint();
1094}
1095
1096void TypeSwitchInfo::TypeSwitchInfoVerify() {
1097  CHECK(IsTypeSwitchInfo());
1098  VerifyPointer(types());
1099}
1100
1101void TypeSwitchInfo::TypeSwitchInfoPrint() {
1102  HeapObject::PrintHeader("TypeSwitchInfo");
1103  PrintF("\n - types: ");
1104  types()->ShortPrint();
1105}
1106
1107
1108void Script::ScriptVerify() {
1109  CHECK(IsScript());
1110  VerifyPointer(source());
1111  VerifyPointer(name());
1112  line_offset()->SmiVerify();
1113  column_offset()->SmiVerify();
1114  VerifyPointer(data());
1115  VerifyPointer(wrapper());
1116  type()->SmiVerify();
1117  VerifyPointer(line_ends());
1118  VerifyPointer(id());
1119}
1120
1121
1122void Script::ScriptPrint() {
1123  HeapObject::PrintHeader("Script");
1124  PrintF("\n - source: ");
1125  source()->ShortPrint();
1126  PrintF("\n - name: ");
1127  name()->ShortPrint();
1128  PrintF("\n - line_offset: ");
1129  line_offset()->ShortPrint();
1130  PrintF("\n - column_offset: ");
1131  column_offset()->ShortPrint();
1132  PrintF("\n - type: ");
1133  type()->ShortPrint();
1134  PrintF("\n - id: ");
1135  id()->ShortPrint();
1136  PrintF("\n - data: ");
1137  data()->ShortPrint();
1138  PrintF("\n - context data: ");
1139  context_data()->ShortPrint();
1140  PrintF("\n - wrapper: ");
1141  wrapper()->ShortPrint();
1142  PrintF("\n - compilation type: ");
1143  compilation_type()->ShortPrint();
1144  PrintF("\n - line ends: ");
1145  line_ends()->ShortPrint();
1146  PrintF("\n - eval from shared: ");
1147  eval_from_shared()->ShortPrint();
1148  PrintF("\n - eval from instructions offset: ");
1149  eval_from_instructions_offset()->ShortPrint();
1150  PrintF("\n");
1151}
1152
1153
1154#ifdef ENABLE_DEBUGGER_SUPPORT
1155void DebugInfo::DebugInfoVerify() {
1156  CHECK(IsDebugInfo());
1157  VerifyPointer(shared());
1158  VerifyPointer(original_code());
1159  VerifyPointer(code());
1160  VerifyPointer(break_points());
1161}
1162
1163
1164void DebugInfo::DebugInfoPrint() {
1165  HeapObject::PrintHeader("DebugInfo");
1166  PrintF("\n - shared: ");
1167  shared()->ShortPrint();
1168  PrintF("\n - original_code: ");
1169  original_code()->ShortPrint();
1170  PrintF("\n - code: ");
1171  code()->ShortPrint();
1172  PrintF("\n - break_points: ");
1173  break_points()->Print();
1174}
1175
1176
1177void BreakPointInfo::BreakPointInfoVerify() {
1178  CHECK(IsBreakPointInfo());
1179  code_position()->SmiVerify();
1180  source_position()->SmiVerify();
1181  statement_position()->SmiVerify();
1182  VerifyPointer(break_point_objects());
1183}
1184
1185
1186void BreakPointInfo::BreakPointInfoPrint() {
1187  HeapObject::PrintHeader("BreakPointInfo");
1188  PrintF("\n - code_position: %d", code_position());
1189  PrintF("\n - source_position: %d", source_position());
1190  PrintF("\n - statement_position: %d", statement_position());
1191  PrintF("\n - break_point_objects: ");
1192  break_point_objects()->ShortPrint();
1193}
1194#endif
1195
1196
1197void JSObject::IncrementSpillStatistics(SpillInformation* info) {
1198  info->number_of_objects_++;
1199  // Named properties
1200  if (HasFastProperties()) {
1201    info->number_of_objects_with_fast_properties_++;
1202    info->number_of_fast_used_fields_   += map()->NextFreePropertyIndex();
1203    info->number_of_fast_unused_fields_ += map()->unused_property_fields();
1204  } else {
1205    StringDictionary* dict = property_dictionary();
1206    info->number_of_slow_used_properties_ += dict->NumberOfElements();
1207    info->number_of_slow_unused_properties_ +=
1208        dict->Capacity() - dict->NumberOfElements();
1209  }
1210  // Indexed properties
1211  switch (GetElementsKind()) {
1212    case FAST_ELEMENTS: {
1213      info->number_of_objects_with_fast_elements_++;
1214      int holes = 0;
1215      FixedArray* e = FixedArray::cast(elements());
1216      int len = e->length();
1217      for (int i = 0; i < len; i++) {
1218        if (e->get(i) == Heap::the_hole_value()) holes++;
1219      }
1220      info->number_of_fast_used_elements_   += len - holes;
1221      info->number_of_fast_unused_elements_ += holes;
1222      break;
1223    }
1224    case PIXEL_ELEMENTS: {
1225      info->number_of_objects_with_fast_elements_++;
1226      PixelArray* e = PixelArray::cast(elements());
1227      info->number_of_fast_used_elements_ += e->length();
1228      break;
1229    }
1230    case DICTIONARY_ELEMENTS: {
1231      NumberDictionary* dict = element_dictionary();
1232      info->number_of_slow_used_elements_ += dict->NumberOfElements();
1233      info->number_of_slow_unused_elements_ +=
1234          dict->Capacity() - dict->NumberOfElements();
1235      break;
1236    }
1237    default:
1238      UNREACHABLE();
1239      break;
1240  }
1241}
1242
1243
1244void JSObject::SpillInformation::Clear() {
1245  number_of_objects_ = 0;
1246  number_of_objects_with_fast_properties_ = 0;
1247  number_of_objects_with_fast_elements_ = 0;
1248  number_of_fast_used_fields_ = 0;
1249  number_of_fast_unused_fields_ = 0;
1250  number_of_slow_used_properties_ = 0;
1251  number_of_slow_unused_properties_ = 0;
1252  number_of_fast_used_elements_ = 0;
1253  number_of_fast_unused_elements_ = 0;
1254  number_of_slow_used_elements_ = 0;
1255  number_of_slow_unused_elements_ = 0;
1256}
1257
1258void JSObject::SpillInformation::Print() {
1259  PrintF("\n  JSObject Spill Statistics (#%d):\n", number_of_objects_);
1260
1261  PrintF("    - fast properties (#%d): %d (used) %d (unused)\n",
1262         number_of_objects_with_fast_properties_,
1263         number_of_fast_used_fields_, number_of_fast_unused_fields_);
1264
1265  PrintF("    - slow properties (#%d): %d (used) %d (unused)\n",
1266         number_of_objects_ - number_of_objects_with_fast_properties_,
1267         number_of_slow_used_properties_, number_of_slow_unused_properties_);
1268
1269  PrintF("    - fast elements (#%d): %d (used) %d (unused)\n",
1270         number_of_objects_with_fast_elements_,
1271         number_of_fast_used_elements_, number_of_fast_unused_elements_);
1272
1273  PrintF("    - slow elements (#%d): %d (used) %d (unused)\n",
1274         number_of_objects_ - number_of_objects_with_fast_elements_,
1275         number_of_slow_used_elements_, number_of_slow_unused_elements_);
1276
1277  PrintF("\n");
1278}
1279
1280
1281void DescriptorArray::PrintDescriptors() {
1282  PrintF("Descriptor array  %d\n", number_of_descriptors());
1283  for (int i = 0; i < number_of_descriptors(); i++) {
1284    PrintF(" %d: ", i);
1285    Descriptor desc;
1286    Get(i, &desc);
1287    desc.Print();
1288  }
1289  PrintF("\n");
1290}
1291
1292
1293bool DescriptorArray::IsSortedNoDuplicates() {
1294  String* current_key = NULL;
1295  uint32_t current = 0;
1296  for (int i = 0; i < number_of_descriptors(); i++) {
1297    String* key = GetKey(i);
1298    if (key == current_key) {
1299      PrintDescriptors();
1300      return false;
1301    }
1302    current_key = key;
1303    uint32_t hash = GetKey(i)->Hash();
1304    if (hash < current) {
1305      PrintDescriptors();
1306      return false;
1307    }
1308    current = hash;
1309  }
1310  return true;
1311}
1312
1313
1314#endif  // DEBUG
1315
1316} }  // namespace v8::internal
1317