f45a035451f63f2b16af25a748abb4d5bec9bac4
[platform/upstream/v8.git] / src / objects-printer.cc
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
3 // found in the LICENSE file.
4
5 #include "src/v8.h"
6
7 #include "src/disasm.h"
8 #include "src/disassembler.h"
9 #include "src/heap/objects-visiting.h"
10 #include "src/interpreter/bytecodes.h"
11 #include "src/jsregexp.h"
12 #include "src/ostreams.h"
13
14 namespace v8 {
15 namespace internal {
16
17 #ifdef OBJECT_PRINT
18
19 void Object::Print() {
20   OFStream os(stdout);
21   this->Print(os);
22   os << std::flush;
23 }
24
25
26 void Object::Print(std::ostream& os) {  // NOLINT
27   if (IsSmi()) {
28     Smi::cast(this)->SmiPrint(os);
29   } else {
30     HeapObject::cast(this)->HeapObjectPrint(os);
31   }
32 }
33
34
35 void HeapObject::PrintHeader(std::ostream& os, const char* id) {  // NOLINT
36   os << "" << reinterpret_cast<void*>(this) << ": [" << id << "]\n";
37 }
38
39
40 void HeapObject::HeapObjectPrint(std::ostream& os) {  // NOLINT
41   InstanceType instance_type = map()->instance_type();
42
43   HandleScope scope(GetIsolate());
44   if (instance_type < FIRST_NONSTRING_TYPE) {
45     String::cast(this)->StringPrint(os);
46     return;
47   }
48
49   switch (instance_type) {
50     case SYMBOL_TYPE:
51       Symbol::cast(this)->SymbolPrint(os);
52       break;
53     case MAP_TYPE:
54       Map::cast(this)->MapPrint(os);
55       break;
56     case HEAP_NUMBER_TYPE:
57       HeapNumber::cast(this)->HeapNumberPrint(os);
58       break;
59     case MUTABLE_HEAP_NUMBER_TYPE:
60       os << "<mutable ";
61       HeapNumber::cast(this)->HeapNumberPrint(os);
62       os << ">";
63       break;
64     case FLOAT32X4_TYPE:
65       Float32x4::cast(this)->Float32x4Print(os);
66       break;
67     case FIXED_DOUBLE_ARRAY_TYPE:
68       FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os);
69       break;
70     case FIXED_ARRAY_TYPE:
71       FixedArray::cast(this)->FixedArrayPrint(os);
72       break;
73     case BYTE_ARRAY_TYPE:
74       ByteArray::cast(this)->ByteArrayPrint(os);
75       break;
76     case BYTECODE_ARRAY_TYPE:
77       BytecodeArray::cast(this)->BytecodeArrayPrint(os);
78       break;
79     case FREE_SPACE_TYPE:
80       FreeSpace::cast(this)->FreeSpacePrint(os);
81       break;
82
83 #define PRINT_EXTERNAL_ARRAY(Type, type, TYPE, ctype, size)            \
84   case EXTERNAL_##TYPE##_ARRAY_TYPE:                                   \
85     External##Type##Array::cast(this)->External##Type##ArrayPrint(os); \
86     break;
87
88      TYPED_ARRAYS(PRINT_EXTERNAL_ARRAY)
89 #undef PRINT_EXTERNAL_ARRAY
90
91 #define PRINT_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
92   case Fixed##Type##Array::kInstanceType:                      \
93     Fixed##Type##Array::cast(this)->FixedTypedArrayPrint(os);  \
94     break;
95
96     TYPED_ARRAYS(PRINT_FIXED_TYPED_ARRAY)
97 #undef PRINT_FIXED_TYPED_ARRAY
98
99     case FILLER_TYPE:
100       os << "filler";
101       break;
102     case JS_OBJECT_TYPE:  // fall through
103     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
104     case JS_ARRAY_TYPE:
105     case JS_GENERATOR_OBJECT_TYPE:
106     case JS_REGEXP_TYPE:
107       JSObject::cast(this)->JSObjectPrint(os);
108       break;
109     case ODDBALL_TYPE:
110       Oddball::cast(this)->to_string()->Print(os);
111       break;
112     case JS_MODULE_TYPE:
113       JSModule::cast(this)->JSModulePrint(os);
114       break;
115     case JS_FUNCTION_TYPE:
116       JSFunction::cast(this)->JSFunctionPrint(os);
117       break;
118     case JS_GLOBAL_PROXY_TYPE:
119       JSGlobalProxy::cast(this)->JSGlobalProxyPrint(os);
120       break;
121     case JS_GLOBAL_OBJECT_TYPE:
122       JSGlobalObject::cast(this)->JSGlobalObjectPrint(os);
123       break;
124     case JS_BUILTINS_OBJECT_TYPE:
125       JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint(os);
126       break;
127     case JS_VALUE_TYPE:
128       os << "Value wrapper around:";
129       JSValue::cast(this)->value()->Print(os);
130       break;
131     case JS_DATE_TYPE:
132       JSDate::cast(this)->JSDatePrint(os);
133       break;
134     case CODE_TYPE:
135       Code::cast(this)->CodePrint(os);
136       break;
137     case JS_PROXY_TYPE:
138       JSProxy::cast(this)->JSProxyPrint(os);
139       break;
140     case JS_FUNCTION_PROXY_TYPE:
141       JSFunctionProxy::cast(this)->JSFunctionProxyPrint(os);
142       break;
143     case JS_SET_TYPE:
144       JSSet::cast(this)->JSSetPrint(os);
145       break;
146     case JS_MAP_TYPE:
147       JSMap::cast(this)->JSMapPrint(os);
148       break;
149     case JS_SET_ITERATOR_TYPE:
150       JSSetIterator::cast(this)->JSSetIteratorPrint(os);
151       break;
152     case JS_MAP_ITERATOR_TYPE:
153       JSMapIterator::cast(this)->JSMapIteratorPrint(os);
154       break;
155     case JS_WEAK_MAP_TYPE:
156       JSWeakMap::cast(this)->JSWeakMapPrint(os);
157       break;
158     case JS_WEAK_SET_TYPE:
159       JSWeakSet::cast(this)->JSWeakSetPrint(os);
160       break;
161     case FOREIGN_TYPE:
162       Foreign::cast(this)->ForeignPrint(os);
163       break;
164     case SHARED_FUNCTION_INFO_TYPE:
165       SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(os);
166       break;
167     case JS_MESSAGE_OBJECT_TYPE:
168       JSMessageObject::cast(this)->JSMessageObjectPrint(os);
169       break;
170     case CELL_TYPE:
171       Cell::cast(this)->CellPrint(os);
172       break;
173     case PROPERTY_CELL_TYPE:
174       PropertyCell::cast(this)->PropertyCellPrint(os);
175       break;
176     case WEAK_CELL_TYPE:
177       WeakCell::cast(this)->WeakCellPrint(os);
178       break;
179     case JS_ARRAY_BUFFER_TYPE:
180       JSArrayBuffer::cast(this)->JSArrayBufferPrint(os);
181       break;
182     case JS_TYPED_ARRAY_TYPE:
183       JSTypedArray::cast(this)->JSTypedArrayPrint(os);
184       break;
185     case JS_DATA_VIEW_TYPE:
186       JSDataView::cast(this)->JSDataViewPrint(os);
187       break;
188 #define MAKE_STRUCT_CASE(NAME, Name, name) \
189   case NAME##_TYPE:                        \
190     Name::cast(this)->Name##Print(os);     \
191     break;
192   STRUCT_LIST(MAKE_STRUCT_CASE)
193 #undef MAKE_STRUCT_CASE
194
195     default:
196       os << "UNKNOWN TYPE " << map()->instance_type();
197       UNREACHABLE();
198       break;
199   }
200 }
201
202
203 void ByteArray::ByteArrayPrint(std::ostream& os) {  // NOLINT
204   os << "byte array, data starts at " << GetDataStartAddress();
205 }
206
207
208 void BytecodeArray::BytecodeArrayPrint(std::ostream& os) {  // NOLINT
209   Disassemble(os);
210 }
211
212
213 void FreeSpace::FreeSpacePrint(std::ostream& os) {  // NOLINT
214   os << "free space, size " << Size();
215 }
216
217
218 #define EXTERNAL_ARRAY_PRINTER(Type, type, TYPE, ctype, size)                \
219   void External##Type##Array::External##Type##ArrayPrint(std::ostream& os) { \
220     os << "external " #type " array";                                        \
221   }
222
223 TYPED_ARRAYS(EXTERNAL_ARRAY_PRINTER)
224
225 #undef EXTERNAL_ARRAY_PRINTER
226
227
228 template <class Traits>
229 void FixedTypedArray<Traits>::FixedTypedArrayPrint(
230     std::ostream& os) {  // NOLINT
231   os << "fixed " << Traits::Designator();
232 }
233
234
235 void JSObject::PrintProperties(std::ostream& os) {  // NOLINT
236   if (HasFastProperties()) {
237     DescriptorArray* descs = map()->instance_descriptors();
238     for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
239       os << "   ";
240       descs->GetKey(i)->NamePrint(os);
241       os << ": ";
242       switch (descs->GetType(i)) {
243         case DATA: {
244           FieldIndex index = FieldIndex::ForDescriptor(map(), i);
245           if (IsUnboxedDoubleField(index)) {
246             os << "<unboxed double> " << RawFastDoublePropertyAt(index);
247           } else {
248             os << Brief(RawFastPropertyAt(index));
249           }
250           os << " (data field at offset " << index.property_index() << ")\n";
251           break;
252         }
253         case ACCESSOR: {
254           FieldIndex index = FieldIndex::ForDescriptor(map(), i);
255           os << " (accessor field at offset " << index.property_index()
256              << ")\n";
257           break;
258         }
259         case DATA_CONSTANT:
260           os << Brief(descs->GetConstant(i)) << " (data constant)\n";
261           break;
262         case ACCESSOR_CONSTANT:
263           os << Brief(descs->GetCallbacksObject(i)) << " (accessor constant)\n";
264           break;
265       }
266     }
267   } else if (IsGlobalObject()) {
268     global_dictionary()->Print(os);
269   } else {
270     property_dictionary()->Print(os);
271   }
272 }
273
274
275 template <class T>
276 static void DoPrintElements(std::ostream& os, Object* object) {  // NOLINT
277   T* p = T::cast(object);
278   for (int i = 0; i < p->length(); i++) {
279     os << "   " << i << ": " << p->get_scalar(i) << "\n";
280   }
281 }
282
283
284 void JSObject::PrintElements(std::ostream& os) {  // NOLINT
285   // Don't call GetElementsKind, its validation code can cause the printer to
286   // fail when debugging.
287   switch (map()->elements_kind()) {
288     case FAST_HOLEY_SMI_ELEMENTS:
289     case FAST_SMI_ELEMENTS:
290     case FAST_HOLEY_ELEMENTS:
291     case FAST_ELEMENTS: {
292       // Print in array notation for non-sparse arrays.
293       FixedArray* p = FixedArray::cast(elements());
294       for (int i = 0; i < p->length(); i++) {
295         os << "   " << i << ": " << Brief(p->get(i)) << "\n";
296       }
297       break;
298     }
299     case FAST_HOLEY_DOUBLE_ELEMENTS:
300     case FAST_DOUBLE_ELEMENTS: {
301       // Print in array notation for non-sparse arrays.
302       if (elements()->length() > 0) {
303         FixedDoubleArray* p = FixedDoubleArray::cast(elements());
304         for (int i = 0; i < p->length(); i++) {
305           os << "   " << i << ": ";
306           if (p->is_the_hole(i)) {
307             os << "<the hole>";
308           } else {
309             os << p->get_scalar(i);
310           }
311           os << "\n";
312         }
313       }
314       break;
315     }
316
317
318 #define PRINT_ELEMENTS(Kind, Type)         \
319   case Kind: {                             \
320     DoPrintElements<Type>(os, elements()); \
321     break;                                 \
322   }
323
324     PRINT_ELEMENTS(EXTERNAL_UINT8_CLAMPED_ELEMENTS, ExternalUint8ClampedArray)
325     PRINT_ELEMENTS(EXTERNAL_INT8_ELEMENTS, ExternalInt8Array)
326     PRINT_ELEMENTS(EXTERNAL_UINT8_ELEMENTS,
327         ExternalUint8Array)
328     PRINT_ELEMENTS(EXTERNAL_INT16_ELEMENTS, ExternalInt16Array)
329     PRINT_ELEMENTS(EXTERNAL_UINT16_ELEMENTS,
330         ExternalUint16Array)
331     PRINT_ELEMENTS(EXTERNAL_INT32_ELEMENTS, ExternalInt32Array)
332     PRINT_ELEMENTS(EXTERNAL_UINT32_ELEMENTS,
333         ExternalUint32Array)
334     PRINT_ELEMENTS(EXTERNAL_FLOAT32_ELEMENTS, ExternalFloat32Array)
335     PRINT_ELEMENTS(EXTERNAL_FLOAT64_ELEMENTS, ExternalFloat64Array)
336
337     PRINT_ELEMENTS(UINT8_ELEMENTS, FixedUint8Array)
338     PRINT_ELEMENTS(UINT8_CLAMPED_ELEMENTS, FixedUint8ClampedArray)
339     PRINT_ELEMENTS(INT8_ELEMENTS, FixedInt8Array)
340     PRINT_ELEMENTS(UINT16_ELEMENTS, FixedUint16Array)
341     PRINT_ELEMENTS(INT16_ELEMENTS, FixedInt16Array)
342     PRINT_ELEMENTS(UINT32_ELEMENTS, FixedUint32Array)
343     PRINT_ELEMENTS(INT32_ELEMENTS, FixedInt32Array)
344     PRINT_ELEMENTS(FLOAT32_ELEMENTS, FixedFloat32Array)
345     PRINT_ELEMENTS(FLOAT64_ELEMENTS, FixedFloat64Array)
346
347 #undef PRINT_ELEMENTS
348
349     case DICTIONARY_ELEMENTS:
350       elements()->Print(os);
351       break;
352     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
353     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
354       FixedArray* p = FixedArray::cast(elements());
355       os << "   parameter map:";
356       for (int i = 2; i < p->length(); i++) {
357         os << " " << (i - 2) << ":" << Brief(p->get(i));
358       }
359       os << "\n   context: " << Brief(p->get(0))
360          << "\n   arguments: " << Brief(p->get(1)) << "\n";
361       break;
362     }
363   }
364 }
365
366
367 void JSObject::JSObjectPrint(std::ostream& os) {  // NOLINT
368   HeapObject::PrintHeader(os, "JSObject");
369   // Don't call GetElementsKind, its validation code can cause the printer to
370   // fail when debugging.
371   PrototypeIterator iter(GetIsolate(), this);
372   os << " - map = " << reinterpret_cast<void*>(map()) << " ["
373      << ElementsKindToString(this->map()->elements_kind())
374      << "]\n - prototype = " << reinterpret_cast<void*>(iter.GetCurrent())
375      << "\n {\n";
376   PrintProperties(os);
377   PrintTransitions(os);
378   PrintElements(os);
379   os << " }\n";
380 }
381
382
383 void JSModule::JSModulePrint(std::ostream& os) {  // NOLINT
384   HeapObject::PrintHeader(os, "JSModule");
385   os << " - map = " << reinterpret_cast<void*>(map()) << "\n"
386      << " - context = ";
387   context()->Print(os);
388   os << " - scope_info = " << Brief(scope_info())
389      << ElementsKindToString(this->map()->elements_kind()) << " {\n";
390   PrintProperties(os);
391   PrintElements(os);
392   os << " }\n";
393 }
394
395
396 static const char* TypeToString(InstanceType type) {
397   switch (type) {
398 #define TYPE_TO_STRING(TYPE) case TYPE: return #TYPE;
399   INSTANCE_TYPE_LIST(TYPE_TO_STRING)
400 #undef TYPE_TO_STRING
401   }
402   UNREACHABLE();
403   return "UNKNOWN";  // Keep the compiler happy.
404 }
405
406
407 void Symbol::SymbolPrint(std::ostream& os) {  // NOLINT
408   HeapObject::PrintHeader(os, "Symbol");
409   os << " - hash: " << Hash();
410   os << "\n - name: " << Brief(name());
411   if (name()->IsUndefined()) {
412     os << " (" << PrivateSymbolToName() << ")";
413   }
414   os << "\n - private: " << is_private();
415   os << "\n";
416 }
417
418
419 void Map::MapPrint(std::ostream& os) {  // NOLINT
420   HeapObject::PrintHeader(os, "Map");
421   os << " - type: " << TypeToString(instance_type()) << "\n";
422   os << " - instance size: " << instance_size() << "\n";
423   os << " - inobject properties: " << inobject_properties() << "\n";
424   os << " - elements kind: " << ElementsKindToString(elements_kind()) << "\n";
425   os << " - unused property fields: " << unused_property_fields() << "\n";
426   if (is_deprecated()) os << " - deprecated_map\n";
427   if (is_stable()) os << " - stable_map\n";
428   if (is_dictionary_map()) os << " - dictionary_map\n";
429   if (is_hidden_prototype()) os << " - hidden_prototype\n";
430   if (has_named_interceptor()) os << " - named_interceptor\n";
431   if (has_indexed_interceptor()) os << " - indexed_interceptor\n";
432   if (is_undetectable()) os << " - undetectable\n";
433   if (has_instance_call_handler()) os << " - instance_call_handler\n";
434   if (is_access_check_needed()) os << " - access_check_needed\n";
435   if (!is_extensible()) os << " - non-extensible\n";
436   if (is_observed()) os << " - observed\n";
437   if (is_prototype_map()) {
438     os << " - prototype_map\n";
439     os << " - prototype info: " << Brief(prototype_info());
440   } else {
441     os << " - back pointer: " << Brief(GetBackPointer());
442   }
443   os << "\n - instance descriptors " << (owns_descriptors() ? "(own) " : "")
444      << "#" << NumberOfOwnDescriptors() << ": "
445      << Brief(instance_descriptors());
446   if (FLAG_unbox_double_fields) {
447     os << "\n - layout descriptor: " << Brief(layout_descriptor());
448   }
449   if (TransitionArray::NumberOfTransitions(raw_transitions()) > 0) {
450     os << "\n - transitions: ";
451     TransitionArray::PrintTransitions(os, raw_transitions());
452   }
453   os << "\n - prototype: " << Brief(prototype());
454   os << "\n - constructor: " << Brief(GetConstructor());
455   os << "\n - code cache: " << Brief(code_cache());
456   os << "\n - dependent code: " << Brief(dependent_code());
457   os << "\n";
458 }
459
460
461 void CodeCache::CodeCachePrint(std::ostream& os) {  // NOLINT
462   HeapObject::PrintHeader(os, "CodeCache");
463   os << "\n - default_cache: " << Brief(default_cache());
464   os << "\n - normal_type_cache: " << Brief(normal_type_cache());
465 }
466
467
468 void PolymorphicCodeCache::PolymorphicCodeCachePrint(
469     std::ostream& os) {  // NOLINT
470   HeapObject::PrintHeader(os, "PolymorphicCodeCache");
471   os << "\n - cache: " << Brief(cache());
472 }
473
474
475 void TypeFeedbackInfo::TypeFeedbackInfoPrint(std::ostream& os) {  // NOLINT
476   HeapObject::PrintHeader(os, "TypeFeedbackInfo");
477   os << " - ic_total_count: " << ic_total_count()
478      << ", ic_with_type_info_count: " << ic_with_type_info_count()
479      << ", ic_generic_count: " << ic_generic_count() << "\n";
480 }
481
482
483 void AliasedArgumentsEntry::AliasedArgumentsEntryPrint(
484     std::ostream& os) {  // NOLINT
485   HeapObject::PrintHeader(os, "AliasedArgumentsEntry");
486   os << "\n - aliased_context_slot: " << aliased_context_slot();
487 }
488
489
490 void FixedArray::FixedArrayPrint(std::ostream& os) {  // NOLINT
491   HeapObject::PrintHeader(os, "FixedArray");
492   os << " - length: " << length();
493   for (int i = 0; i < length(); i++) {
494     os << "\n  [" << i << "]: " << Brief(get(i));
495   }
496   os << "\n";
497 }
498
499
500 void FixedDoubleArray::FixedDoubleArrayPrint(std::ostream& os) {  // NOLINT
501   HeapObject::PrintHeader(os, "FixedDoubleArray");
502   os << " - length: " << length();
503   for (int i = 0; i < length(); i++) {
504     os << "\n  [" << i << "]: ";
505     if (is_the_hole(i)) {
506       os << "<the hole>";
507     } else {
508       os << get_scalar(i);
509     }
510   }
511   os << "\n";
512 }
513
514
515 void TypeFeedbackVector::Print() {
516   OFStream os(stdout);
517   TypeFeedbackVectorPrint(os);
518   os << std::flush;
519 }
520
521
522 void TypeFeedbackVector::TypeFeedbackVectorPrint(std::ostream& os) {  // NOLINT
523   HeapObject::PrintHeader(os, "TypeFeedbackVector");
524   os << " - length: " << length();
525   if (length() == 0) {
526     os << " (empty)\n";
527     return;
528   }
529
530   os << "\n - ics with type info: " << ic_with_type_info_count();
531   os << "\n - generic ics: " << ic_generic_count();
532
533   if (Slots() > 0) {
534     for (int i = 0; i < Slots(); i++) {
535       FeedbackVectorSlot slot(i);
536       os << "\n Slot " << i << " [" << GetIndex(slot)
537          << "]: " << Brief(Get(slot));
538     }
539   }
540
541   if (ICSlots() > 0) {
542     DCHECK(elements_per_ic_slot() == 2);
543
544     for (int i = 0; i < ICSlots(); i++) {
545       FeedbackVectorICSlot slot(i);
546       Code::Kind kind = GetKind(slot);
547       os << "\n ICSlot " << i;
548       if (kind == Code::LOAD_IC) {
549         LoadICNexus nexus(this, slot);
550         os << " LOAD_IC " << Code::ICState2String(nexus.StateFromFeedback());
551       } else if (kind == Code::KEYED_LOAD_IC) {
552         KeyedLoadICNexus nexus(this, slot);
553         os << " KEYED_LOAD_IC "
554            << Code::ICState2String(nexus.StateFromFeedback());
555       } else {
556         DCHECK(kind == Code::CALL_IC);
557         CallICNexus nexus(this, slot);
558         os << " CALL_IC " << Code::ICState2String(nexus.StateFromFeedback());
559       }
560
561       os << "\n  [" << GetIndex(slot) << "]: " << Brief(Get(slot));
562       os << "\n  [" << (GetIndex(slot) + 1)
563          << "]: " << Brief(get(GetIndex(slot) + 1));
564     }
565   }
566   os << "\n";
567 }
568
569
570 void JSValue::JSValuePrint(std::ostream& os) {  // NOLINT
571   HeapObject::PrintHeader(os, "ValueObject");
572   value()->Print(os);
573 }
574
575
576 void JSMessageObject::JSMessageObjectPrint(std::ostream& os) {  // NOLINT
577   HeapObject::PrintHeader(os, "JSMessageObject");
578   os << " - type: " << type();
579   os << "\n - arguments: " << Brief(argument());
580   os << "\n - start_position: " << start_position();
581   os << "\n - end_position: " << end_position();
582   os << "\n - script: " << Brief(script());
583   os << "\n - stack_frames: " << Brief(stack_frames());
584   os << "\n";
585 }
586
587
588 void String::StringPrint(std::ostream& os) {  // NOLINT
589   if (StringShape(this).IsInternalized()) {
590     os << "#";
591   } else if (StringShape(this).IsCons()) {
592     os << "c\"";
593   } else {
594     os << "\"";
595   }
596
597   const char truncated_epilogue[] = "...<truncated>";
598   int len = length();
599   if (!FLAG_use_verbose_printer) {
600     if (len > 100) {
601       len = 100 - sizeof(truncated_epilogue);
602     }
603   }
604   for (int i = 0; i < len; i++) {
605     os << AsUC16(Get(i));
606   }
607   if (len != length()) {
608     os << truncated_epilogue;
609   }
610
611   if (!StringShape(this).IsInternalized()) os << "\"";
612 }
613
614
615 void Name::NamePrint(std::ostream& os) {  // NOLINT
616   if (IsString()) {
617     String::cast(this)->StringPrint(os);
618   } else if (IsSymbol()) {
619     Symbol::cast(this)->name()->Print(os);
620   } else {
621     os << Brief(this);
622   }
623 }
624
625
626 static const char* const weekdays[] = {
627   "???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
628 };
629
630
631 void JSDate::JSDatePrint(std::ostream& os) {  // NOLINT
632   HeapObject::PrintHeader(os, "JSDate");
633   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
634   os << " - value = ";
635   value()->Print(os);
636   if (!year()->IsSmi()) {
637     os << " - time = NaN\n";
638   } else {
639     // TODO(svenpanne) Add some basic formatting to our streams.
640     ScopedVector<char> buf(100);
641     SNPrintF(
642         buf, " - time = %s %04d/%02d/%02d %02d:%02d:%02d\n",
643         weekdays[weekday()->IsSmi() ? Smi::cast(weekday())->value() + 1 : 0],
644         year()->IsSmi() ? Smi::cast(year())->value() : -1,
645         month()->IsSmi() ? Smi::cast(month())->value() : -1,
646         day()->IsSmi() ? Smi::cast(day())->value() : -1,
647         hour()->IsSmi() ? Smi::cast(hour())->value() : -1,
648         min()->IsSmi() ? Smi::cast(min())->value() : -1,
649         sec()->IsSmi() ? Smi::cast(sec())->value() : -1);
650     os << buf.start();
651   }
652 }
653
654
655 void JSProxy::JSProxyPrint(std::ostream& os) {  // NOLINT
656   HeapObject::PrintHeader(os, "JSProxy");
657   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
658   os << " - handler = ";
659   handler()->Print(os);
660   os << "\n - hash = ";
661   hash()->Print(os);
662   os << "\n";
663 }
664
665
666 void JSFunctionProxy::JSFunctionProxyPrint(std::ostream& os) {  // NOLINT
667   HeapObject::PrintHeader(os, "JSFunctionProxy");
668   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
669   os << " - handler = ";
670   handler()->Print(os);
671   os << "\n - call_trap = ";
672   call_trap()->Print(os);
673   os << "\n - construct_trap = ";
674   construct_trap()->Print(os);
675   os << "\n";
676 }
677
678
679 void JSSet::JSSetPrint(std::ostream& os) {  // NOLINT
680   HeapObject::PrintHeader(os, "JSSet");
681   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
682   os << " - table = " << Brief(table());
683   os << "\n";
684 }
685
686
687 void JSMap::JSMapPrint(std::ostream& os) {  // NOLINT
688   HeapObject::PrintHeader(os, "JSMap");
689   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
690   os << " - table = " << Brief(table());
691   os << "\n";
692 }
693
694
695 template <class Derived, class TableType>
696 void
697 OrderedHashTableIterator<Derived, TableType>::OrderedHashTableIteratorPrint(
698     std::ostream& os) {  // NOLINT
699   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
700   os << " - table = " << Brief(table());
701   os << "\n - index = " << Brief(index());
702   os << "\n - kind = " << Brief(kind());
703   os << "\n";
704 }
705
706
707 template void OrderedHashTableIterator<
708     JSSetIterator,
709     OrderedHashSet>::OrderedHashTableIteratorPrint(std::ostream& os);  // NOLINT
710
711
712 template void OrderedHashTableIterator<
713     JSMapIterator,
714     OrderedHashMap>::OrderedHashTableIteratorPrint(std::ostream& os);  // NOLINT
715
716
717 void JSSetIterator::JSSetIteratorPrint(std::ostream& os) {  // NOLINT
718   HeapObject::PrintHeader(os, "JSSetIterator");
719   OrderedHashTableIteratorPrint(os);
720 }
721
722
723 void JSMapIterator::JSMapIteratorPrint(std::ostream& os) {  // NOLINT
724   HeapObject::PrintHeader(os, "JSMapIterator");
725   OrderedHashTableIteratorPrint(os);
726 }
727
728
729 void JSWeakMap::JSWeakMapPrint(std::ostream& os) {  // NOLINT
730   HeapObject::PrintHeader(os, "JSWeakMap");
731   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
732   os << " - table = " << Brief(table());
733   os << "\n";
734 }
735
736
737 void JSWeakSet::JSWeakSetPrint(std::ostream& os) {  // NOLINT
738   HeapObject::PrintHeader(os, "JSWeakSet");
739   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
740   os << " - table = " << Brief(table());
741   os << "\n";
742 }
743
744
745 void JSArrayBuffer::JSArrayBufferPrint(std::ostream& os) {  // NOLINT
746   HeapObject::PrintHeader(os, "JSArrayBuffer");
747   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
748   os << " - backing_store = " << backing_store() << "\n";
749   os << " - byte_length = " << Brief(byte_length());
750   if (was_neutered()) os << " - neutered\n";
751   os << "\n";
752 }
753
754
755 void JSTypedArray::JSTypedArrayPrint(std::ostream& os) {  // NOLINT
756   HeapObject::PrintHeader(os, "JSTypedArray");
757   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
758   os << " - buffer = " << Brief(buffer());
759   os << "\n - byte_offset = " << Brief(byte_offset());
760   os << "\n - byte_length = " << Brief(byte_length());
761   os << "\n - length = " << Brief(length());
762   if (WasNeutered()) os << " - neutered\n";
763   os << "\n";
764   if (!WasNeutered()) PrintElements(os);
765 }
766
767
768 void JSDataView::JSDataViewPrint(std::ostream& os) {  // NOLINT
769   HeapObject::PrintHeader(os, "JSDataView");
770   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
771   os << " - buffer =" << Brief(buffer());
772   os << "\n - byte_offset = " << Brief(byte_offset());
773   os << "\n - byte_length = " << Brief(byte_length());
774   if (WasNeutered()) os << " - neutered\n";
775   os << "\n";
776 }
777
778
779 void JSFunction::JSFunctionPrint(std::ostream& os) {  // NOLINT
780   HeapObject::PrintHeader(os, "Function");
781   os << " - map = " << reinterpret_cast<void*>(map()) << "\n";
782   os << " - initial_map = ";
783   if (has_initial_map()) os << Brief(initial_map());
784   os << "\n - shared_info = " << Brief(shared());
785   os << "\n   - name = " << Brief(shared()->name());
786   os << "\n - context = " << Brief(context());
787   if (shared()->bound()) {
788     os << "\n - bindings = " << Brief(function_bindings());
789   } else {
790     os << "\n - literals = " << Brief(literals());
791   }
792   os << "\n - code = " << Brief(code());
793   os << "\n";
794   PrintProperties(os);
795   PrintElements(os);
796   os << "\n";
797 }
798
799
800 void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {  // NOLINT
801   HeapObject::PrintHeader(os, "SharedFunctionInfo");
802   os << " - name: " << Brief(name());
803   os << "\n - expected_nof_properties: " << expected_nof_properties();
804   os << "\n - ast_node_count: " << ast_node_count();
805   os << "\n - instance class name = ";
806   instance_class_name()->Print(os);
807   os << "\n - code = " << Brief(code());
808   if (HasSourceCode()) {
809     os << "\n - source code = ";
810     String* source = String::cast(Script::cast(script())->source());
811     int start = start_position();
812     int length = end_position() - start;
813     base::SmartArrayPointer<char> source_string = source->ToCString(
814         DISALLOW_NULLS, FAST_STRING_TRAVERSAL, start, length, NULL);
815     os << source_string.get();
816   }
817   // Script files are often large, hard to read.
818   // os << "\n - script =";
819   // script()->Print(os);
820   os << "\n - function token position = " << function_token_position();
821   os << "\n - start position = " << start_position();
822   os << "\n - end position = " << end_position();
823   os << "\n - is expression = " << is_expression();
824   os << "\n - debug info = " << Brief(debug_info());
825   os << "\n - length = " << length();
826   os << "\n - optimized_code_map = " << Brief(optimized_code_map());
827   os << "\n - feedback_vector = ";
828   feedback_vector()->TypeFeedbackVectorPrint(os);
829   if (HasBytecodeArray()) {
830     os << "\n - bytecode_array = " << bytecode_array();
831   }
832   os << "\n";
833 }
834
835
836 void JSGlobalProxy::JSGlobalProxyPrint(std::ostream& os) {  // NOLINT
837   os << "global_proxy ";
838   JSObjectPrint(os);
839   os << "native context : " << Brief(native_context());
840   os << "\n";
841 }
842
843
844 void JSGlobalObject::JSGlobalObjectPrint(std::ostream& os) {  // NOLINT
845   os << "global ";
846   JSObjectPrint(os);
847   os << "native context : " << Brief(native_context());
848   os << "\n";
849 }
850
851
852 void JSBuiltinsObject::JSBuiltinsObjectPrint(std::ostream& os) {  // NOLINT
853   os << "builtins ";
854   JSObjectPrint(os);
855 }
856
857
858 void Cell::CellPrint(std::ostream& os) {  // NOLINT
859   HeapObject::PrintHeader(os, "Cell");
860 }
861
862
863 void PropertyCell::PropertyCellPrint(std::ostream& os) {  // NOLINT
864   HeapObject::PrintHeader(os, "PropertyCell");
865 }
866
867
868 void WeakCell::WeakCellPrint(std::ostream& os) {  // NOLINT
869   HeapObject::PrintHeader(os, "WeakCell");
870   if (cleared()) {
871     os << "\n - cleared";
872   } else {
873     os << "\n - value: " << Brief(value());
874   }
875 }
876
877
878 void Code::CodePrint(std::ostream& os) {  // NOLINT
879   HeapObject::PrintHeader(os, "Code");
880 #ifdef ENABLE_DISASSEMBLER
881   if (FLAG_use_verbose_printer) {
882     Disassemble(NULL, os);
883   }
884 #endif
885 }
886
887
888 void Foreign::ForeignPrint(std::ostream& os) {  // NOLINT
889   os << "foreign address : " << foreign_address();
890 }
891
892
893 void ExecutableAccessorInfo::ExecutableAccessorInfoPrint(
894     std::ostream& os) {  // NOLINT
895   HeapObject::PrintHeader(os, "ExecutableAccessorInfo");
896   os << "\n - name: " << Brief(name());
897   os << "\n - flag: " << Brief(flag());
898   os << "\n - getter: " << Brief(getter());
899   os << "\n - setter: " << Brief(setter());
900   os << "\n - data: " << Brief(data());
901   os << "\n";
902 }
903
904
905 void Box::BoxPrint(std::ostream& os) {  // NOLINT
906   HeapObject::PrintHeader(os, "Box");
907   os << "\n - value: " << Brief(value());
908   os << "\n";
909 }
910
911
912 void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) {  // NOLINT
913   HeapObject::PrintHeader(os, "PrototypeInfo");
914   os << "\n - prototype users: " << Brief(prototype_users());
915   os << "\n - validity cell: " << Brief(validity_cell());
916   os << "\n - constructor name: " << Brief(constructor_name());
917   os << "\n";
918 }
919
920
921 void AccessorPair::AccessorPairPrint(std::ostream& os) {  // NOLINT
922   HeapObject::PrintHeader(os, "AccessorPair");
923   os << "\n - getter: " << Brief(getter());
924   os << "\n - setter: " << Brief(setter());
925   os << "\n";
926 }
927
928
929 void AccessCheckInfo::AccessCheckInfoPrint(std::ostream& os) {  // NOLINT
930   HeapObject::PrintHeader(os, "AccessCheckInfo");
931   os << "\n - named_callback: " << Brief(named_callback());
932   os << "\n - indexed_callback: " << Brief(indexed_callback());
933   os << "\n - data: " << Brief(data());
934   os << "\n";
935 }
936
937
938 void InterceptorInfo::InterceptorInfoPrint(std::ostream& os) {  // NOLINT
939   HeapObject::PrintHeader(os, "InterceptorInfo");
940   os << "\n - getter: " << Brief(getter());
941   os << "\n - setter: " << Brief(setter());
942   os << "\n - query: " << Brief(query());
943   os << "\n - deleter: " << Brief(deleter());
944   os << "\n - enumerator: " << Brief(enumerator());
945   os << "\n - data: " << Brief(data());
946   os << "\n";
947 }
948
949
950 void CallHandlerInfo::CallHandlerInfoPrint(std::ostream& os) {  // NOLINT
951   HeapObject::PrintHeader(os, "CallHandlerInfo");
952   os << "\n - callback: " << Brief(callback());
953   os << "\n - data: " << Brief(data());
954   os << "\n";
955 }
956
957
958 void FunctionTemplateInfo::FunctionTemplateInfoPrint(
959     std::ostream& os) {  // NOLINT
960   HeapObject::PrintHeader(os, "FunctionTemplateInfo");
961   os << "\n - class name: " << Brief(class_name());
962   os << "\n - tag: " << Brief(tag());
963   os << "\n - property_list: " << Brief(property_list());
964   os << "\n - serial_number: " << Brief(serial_number());
965   os << "\n - call_code: " << Brief(call_code());
966   os << "\n - property_accessors: " << Brief(property_accessors());
967   os << "\n - prototype_template: " << Brief(prototype_template());
968   os << "\n - parent_template: " << Brief(parent_template());
969   os << "\n - named_property_handler: " << Brief(named_property_handler());
970   os << "\n - indexed_property_handler: " << Brief(indexed_property_handler());
971   os << "\n - instance_template: " << Brief(instance_template());
972   os << "\n - signature: " << Brief(signature());
973   os << "\n - access_check_info: " << Brief(access_check_info());
974   os << "\n - hidden_prototype: " << (hidden_prototype() ? "true" : "false");
975   os << "\n - undetectable: " << (undetectable() ? "true" : "false");
976   os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false");
977   os << "\n - instantiated: " << (instantiated() ? "true" : "false");
978   os << "\n";
979 }
980
981
982 void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) {  // NOLINT
983   HeapObject::PrintHeader(os, "ObjectTemplateInfo");
984   os << " - tag: " << Brief(tag());
985   os << "\n - property_list: " << Brief(property_list());
986   os << "\n - property_accessors: " << Brief(property_accessors());
987   os << "\n - constructor: " << Brief(constructor());
988   os << "\n - internal_field_count: " << Brief(internal_field_count());
989   os << "\n";
990 }
991
992
993 void TypeSwitchInfo::TypeSwitchInfoPrint(std::ostream& os) {  // NOLINT
994   HeapObject::PrintHeader(os, "TypeSwitchInfo");
995   os << "\n - types: " << Brief(types());
996   os << "\n";
997 }
998
999
1000 void AllocationSite::AllocationSitePrint(std::ostream& os) {  // NOLINT
1001   HeapObject::PrintHeader(os, "AllocationSite");
1002   os << " - weak_next: " << Brief(weak_next());
1003   os << "\n - dependent code: " << Brief(dependent_code());
1004   os << "\n - nested site: " << Brief(nested_site());
1005   os << "\n - memento found count: "
1006      << Brief(Smi::FromInt(memento_found_count()));
1007   os << "\n - memento create count: "
1008      << Brief(Smi::FromInt(memento_create_count()));
1009   os << "\n - pretenure decision: "
1010      << Brief(Smi::FromInt(pretenure_decision()));
1011   os << "\n - transition_info: ";
1012   if (transition_info()->IsSmi()) {
1013     ElementsKind kind = GetElementsKind();
1014     os << "Array allocation with ElementsKind " << ElementsKindToString(kind);
1015   } else if (transition_info()->IsJSArray()) {
1016     os << "Array literal " << Brief(transition_info());
1017   } else {
1018     os << "unknown transition_info" << Brief(transition_info());
1019   }
1020   os << "\n";
1021 }
1022
1023
1024 void AllocationMemento::AllocationMementoPrint(std::ostream& os) {  // NOLINT
1025   HeapObject::PrintHeader(os, "AllocationMemento");
1026   os << " - allocation site: ";
1027   if (IsValid()) {
1028     GetAllocationSite()->Print(os);
1029   } else {
1030     os << "<invalid>\n";
1031   }
1032 }
1033
1034
1035 void Script::ScriptPrint(std::ostream& os) {  // NOLINT
1036   HeapObject::PrintHeader(os, "Script");
1037   os << "\n - source: " << Brief(source());
1038   os << "\n - name: " << Brief(name());
1039   os << "\n - line_offset: " << Brief(line_offset());
1040   os << "\n - column_offset: " << Brief(column_offset());
1041   os << "\n - type: " << Brief(type());
1042   os << "\n - id: " << Brief(id());
1043   os << "\n - context data: " << Brief(context_data());
1044   os << "\n - wrapper: " << Brief(wrapper());
1045   os << "\n - compilation type: " << compilation_type();
1046   os << "\n - line ends: " << Brief(line_ends());
1047   os << "\n - eval from shared: " << Brief(eval_from_shared());
1048   os << "\n - eval from instructions offset: "
1049      << Brief(eval_from_instructions_offset());
1050   os << "\n - shared function infos: " << Brief(shared_function_infos());
1051   os << "\n";
1052 }
1053
1054
1055 void DebugInfo::DebugInfoPrint(std::ostream& os) {  // NOLINT
1056   HeapObject::PrintHeader(os, "DebugInfo");
1057   os << "\n - shared: " << Brief(shared());
1058   os << "\n - code: " << Brief(code());
1059   os << "\n - break_points: ";
1060   break_points()->Print(os);
1061 }
1062
1063
1064 void BreakPointInfo::BreakPointInfoPrint(std::ostream& os) {  // NOLINT
1065   HeapObject::PrintHeader(os, "BreakPointInfo");
1066   os << "\n - code_position: " << code_position()->value();
1067   os << "\n - source_position: " << source_position()->value();
1068   os << "\n - statement_position: " << statement_position()->value();
1069   os << "\n - break_point_objects: " << Brief(break_point_objects());
1070   os << "\n";
1071 }
1072
1073
1074 static void PrintBitMask(std::ostream& os, uint32_t value) {  // NOLINT
1075   for (int i = 0; i < 32; i++) {
1076     if ((i & 7) == 0) os << " ";
1077     os << (((value & 1) == 0) ? "_" : "x");
1078     value >>= 1;
1079   }
1080 }
1081
1082
1083 void LayoutDescriptor::Print() {
1084   OFStream os(stdout);
1085   this->Print(os);
1086   os << std::flush;
1087 }
1088
1089
1090 void LayoutDescriptor::Print(std::ostream& os) {  // NOLINT
1091   os << "Layout descriptor: ";
1092   if (IsUninitialized()) {
1093     os << "<uninitialized>";
1094   } else if (IsFastPointerLayout()) {
1095     os << "<all tagged>";
1096   } else if (IsSmi()) {
1097     os << "fast";
1098     PrintBitMask(os, static_cast<uint32_t>(Smi::cast(this)->value()));
1099   } else {
1100     os << "slow";
1101     int len = length();
1102     for (int i = 0; i < len; i++) {
1103       if (i > 0) os << " |";
1104       PrintBitMask(os, get_scalar(i));
1105     }
1106   }
1107   os << "\n";
1108 }
1109
1110
1111 #endif  // OBJECT_PRINT
1112
1113
1114 #if TRACE_MAPS
1115
1116
1117 void Name::NameShortPrint() {
1118   if (this->IsString()) {
1119     PrintF("%s", String::cast(this)->ToCString().get());
1120   } else {
1121     DCHECK(this->IsSymbol());
1122     Symbol* s = Symbol::cast(this);
1123     if (s->name()->IsUndefined()) {
1124       PrintF("#<%s>", s->PrivateSymbolToName());
1125     } else {
1126       PrintF("<%s>", String::cast(s->name())->ToCString().get());
1127     }
1128   }
1129 }
1130
1131
1132 int Name::NameShortPrint(Vector<char> str) {
1133   if (this->IsString()) {
1134     return SNPrintF(str, "%s", String::cast(this)->ToCString().get());
1135   } else {
1136     DCHECK(this->IsSymbol());
1137     Symbol* s = Symbol::cast(this);
1138     if (s->name()->IsUndefined()) {
1139       return SNPrintF(str, "#<%s>", s->PrivateSymbolToName());
1140     } else {
1141       return SNPrintF(str, "<%s>", String::cast(s->name())->ToCString().get());
1142     }
1143   }
1144 }
1145
1146
1147 #endif  // TRACE_MAPS
1148
1149
1150 #if defined(DEBUG) || defined(OBJECT_PRINT)
1151 // This method is only meant to be called from gdb for debugging purposes.
1152 // Since the string can also be in two-byte encoding, non-Latin1 characters
1153 // will be ignored in the output.
1154 char* String::ToAsciiArray() {
1155   // Static so that subsequent calls frees previously allocated space.
1156   // This also means that previous results will be overwritten.
1157   static char* buffer = NULL;
1158   if (buffer != NULL) delete[] buffer;
1159   buffer = new char[length() + 1];
1160   WriteToFlat(this, reinterpret_cast<uint8_t*>(buffer), 0, length());
1161   buffer[length()] = 0;
1162   return buffer;
1163 }
1164
1165
1166 void DescriptorArray::Print() {
1167   OFStream os(stdout);
1168   this->PrintDescriptors(os);
1169   os << std::flush;
1170 }
1171
1172
1173 void DescriptorArray::PrintDescriptors(std::ostream& os) {  // NOLINT
1174   HandleScope scope(GetIsolate());
1175   os << "Descriptor array " << number_of_descriptors() << "\n";
1176   for (int i = 0; i < number_of_descriptors(); i++) {
1177     Descriptor desc;
1178     Get(i, &desc);
1179     os << " " << i << ": " << desc << "\n";
1180   }
1181   os << "\n";
1182 }
1183
1184
1185 void TransitionArray::Print() {
1186   OFStream os(stdout);
1187   TransitionArray::PrintTransitions(os, this);
1188   os << std::flush;
1189 }
1190
1191
1192 void TransitionArray::PrintTransitions(std::ostream& os, Object* transitions,
1193                                        bool print_header) {  // NOLINT
1194   int num_transitions = NumberOfTransitions(transitions);
1195   if (print_header) {
1196     os << "Transition array " << num_transitions << "\n";
1197   }
1198   for (int i = 0; i < num_transitions; i++) {
1199     Name* key = GetKey(transitions, i);
1200     Map* target = GetTarget(transitions, i);
1201     os << "   ";
1202 #ifdef OBJECT_PRINT
1203     key->NamePrint(os);
1204 #else
1205     key->ShortPrint(os);
1206 #endif
1207     os << ": ";
1208     Heap* heap = key->GetHeap();
1209     if (key == heap->nonextensible_symbol()) {
1210       os << " (transition to non-extensible)";
1211     } else if (key == heap->sealed_symbol()) {
1212       os << " (transition to sealed)";
1213     } else if (key == heap->frozen_symbol()) {
1214       os << " (transition to frozen)";
1215     } else if (key == heap->elements_transition_symbol()) {
1216       os << " (transition to " << ElementsKindToString(target->elements_kind())
1217          << ")";
1218     } else if (key == heap->observed_symbol()) {
1219       os << " (transition to Object.observe)";
1220     } else {
1221       PropertyDetails details = GetTargetDetails(key, target);
1222       os << " (transition to ";
1223       if (details.location() == kDescriptor) {
1224         os << "immutable ";
1225       }
1226       os << (details.kind() == kData ? "data" : "accessor");
1227       if (details.location() == kDescriptor) {
1228         Object* value =
1229             target->instance_descriptors()->GetValue(target->LastAdded());
1230         os << " " << Brief(value);
1231       }
1232       os << "), attrs: " << details.attributes();
1233     }
1234     os << " -> " << Brief(target) << "\n";
1235   }
1236 }
1237
1238
1239 void JSObject::PrintTransitions(std::ostream& os) {  // NOLINT
1240   TransitionArray::PrintTransitions(os, map()->raw_transitions());
1241 }
1242 #endif  // defined(DEBUG) || defined(OBJECT_PRINT)
1243 }  // namespace internal
1244 }  // namespace v8