blob: d808a2f2d6cd1c889be9f36213622642d4984c7d [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001#!/usr/bin/env python
2
3#
4# Copyright 2012 the V8 project authors. All rights reserved.
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following
13# disclaimer in the documentation and/or other materials provided
14# with the distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived
17# from this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30#
31
32#
33# Emits a C++ file to be compiled and linked into libv8 to support postmortem
34# debugging tools. Most importantly, this tool emits constants describing V8
35# internals:
36#
37# v8dbg_type_CLASS__TYPE = VALUE Describes class type values
38# v8dbg_class_CLASS__FIELD__TYPE = OFFSET Describes class fields
39# v8dbg_parent_CLASS__PARENT Describes class hierarchy
40# v8dbg_frametype_NAME = VALUE Describes stack frame values
41# v8dbg_off_fp_NAME = OFFSET Frame pointer offsets
42# v8dbg_prop_NAME = OFFSET Object property offsets
43# v8dbg_NAME = VALUE Miscellaneous values
44#
45# These constants are declared as global integers so that they'll be present in
46# the generated libv8 binary.
47#
48
49import re
50import sys
51
52#
53# Miscellaneous constants, tags, and masks used for object identification.
54#
55consts_misc = [
56 { 'name': 'FirstNonstringType', 'value': 'FIRST_NONSTRING_TYPE' },
57
58 { 'name': 'IsNotStringMask', 'value': 'kIsNotStringMask' },
59 { 'name': 'StringTag', 'value': 'kStringTag' },
60 { 'name': 'NotStringTag', 'value': 'kNotStringTag' },
61
62 { 'name': 'StringEncodingMask', 'value': 'kStringEncodingMask' },
63 { 'name': 'TwoByteStringTag', 'value': 'kTwoByteStringTag' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +000064 { 'name': 'OneByteStringTag', 'value': 'kOneByteStringTag' },
Ben Murdoch3ef787d2012-04-12 10:51:47 +010065
66 { 'name': 'StringRepresentationMask',
67 'value': 'kStringRepresentationMask' },
68 { 'name': 'SeqStringTag', 'value': 'kSeqStringTag' },
69 { 'name': 'ConsStringTag', 'value': 'kConsStringTag' },
70 { 'name': 'ExternalStringTag', 'value': 'kExternalStringTag' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 { 'name': 'SlicedStringTag', 'value': 'kSlicedStringTag' },
Ben Murdoch3ef787d2012-04-12 10:51:47 +010072
Ben Murdoch3ef787d2012-04-12 10:51:47 +010073 { 'name': 'HeapObjectTag', 'value': 'kHeapObjectTag' },
74 { 'name': 'HeapObjectTagMask', 'value': 'kHeapObjectTagMask' },
75 { 'name': 'SmiTag', 'value': 'kSmiTag' },
76 { 'name': 'SmiTagMask', 'value': 'kSmiTagMask' },
77 { 'name': 'SmiValueShift', 'value': 'kSmiTagSize' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 { 'name': 'SmiShiftSize', 'value': 'kSmiShiftSize' },
Ben Murdoch3ef787d2012-04-12 10:51:47 +010079 { 'name': 'PointerSizeLog2', 'value': 'kPointerSizeLog2' },
80
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081 { 'name': 'OddballFalse', 'value': 'Oddball::kFalse' },
82 { 'name': 'OddballTrue', 'value': 'Oddball::kTrue' },
83 { 'name': 'OddballTheHole', 'value': 'Oddball::kTheHole' },
84 { 'name': 'OddballNull', 'value': 'Oddball::kNull' },
Ben Murdoch097c5b22016-05-18 11:27:45 +010085 { 'name': 'OddballArgumentsMarker', 'value': 'Oddball::kArgumentsMarker' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086 { 'name': 'OddballUndefined', 'value': 'Oddball::kUndefined' },
87 { 'name': 'OddballUninitialized', 'value': 'Oddball::kUninitialized' },
88 { 'name': 'OddballOther', 'value': 'Oddball::kOther' },
89 { 'name': 'OddballException', 'value': 'Oddball::kException' },
90
Ben Murdoch3ef787d2012-04-12 10:51:47 +010091 { 'name': 'prop_idx_first',
92 'value': 'DescriptorArray::kFirstIndex' },
93 { 'name': 'prop_type_field',
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000094 'value': 'DATA' },
Ben Murdoch097c5b22016-05-18 11:27:45 +010095 { 'name': 'prop_type_const_field',
96 'value': 'DATA_CONSTANT' },
Ben Murdoch3ef787d2012-04-12 10:51:47 +010097 { 'name': 'prop_type_mask',
98 'value': 'PropertyDetails::TypeField::kMask' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +000099 { 'name': 'prop_index_mask',
100 'value': 'PropertyDetails::FieldIndexField::kMask' },
101 { 'name': 'prop_index_shift',
102 'value': 'PropertyDetails::FieldIndexField::kShift' },
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103 { 'name': 'prop_representation_mask',
104 'value': 'PropertyDetails::RepresentationField::kMask' },
105 { 'name': 'prop_representation_shift',
106 'value': 'PropertyDetails::RepresentationField::kShift' },
107 { 'name': 'prop_representation_integer8',
108 'value': 'Representation::Kind::kInteger8' },
109 { 'name': 'prop_representation_uinteger8',
110 'value': 'Representation::Kind::kUInteger8' },
111 { 'name': 'prop_representation_integer16',
112 'value': 'Representation::Kind::kInteger16' },
113 { 'name': 'prop_representation_uinteger16',
114 'value': 'Representation::Kind::kUInteger16' },
115 { 'name': 'prop_representation_smi',
116 'value': 'Representation::Kind::kSmi' },
117 { 'name': 'prop_representation_integer32',
118 'value': 'Representation::Kind::kInteger32' },
119 { 'name': 'prop_representation_double',
120 'value': 'Representation::Kind::kDouble' },
121 { 'name': 'prop_representation_heapobject',
122 'value': 'Representation::Kind::kHeapObject' },
123 { 'name': 'prop_representation_tagged',
124 'value': 'Representation::Kind::kTagged' },
125 { 'name': 'prop_representation_external',
126 'value': 'Representation::Kind::kExternal' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127
128 { 'name': 'prop_desc_key',
129 'value': 'DescriptorArray::kDescriptorKey' },
130 { 'name': 'prop_desc_details',
131 'value': 'DescriptorArray::kDescriptorDetails' },
132 { 'name': 'prop_desc_value',
133 'value': 'DescriptorArray::kDescriptorValue' },
134 { 'name': 'prop_desc_size',
135 'value': 'DescriptorArray::kDescriptorSize' },
136
137 { 'name': 'elements_fast_holey_elements',
138 'value': 'FAST_HOLEY_ELEMENTS' },
139 { 'name': 'elements_fast_elements',
140 'value': 'FAST_ELEMENTS' },
141 { 'name': 'elements_dictionary_elements',
142 'value': 'DICTIONARY_ELEMENTS' },
143
144 { 'name': 'bit_field2_elements_kind_mask',
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 'value': 'Map::ElementsKindBits::kMask' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 { 'name': 'bit_field2_elements_kind_shift',
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 'value': 'Map::ElementsKindBits::kShift' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 { 'name': 'bit_field3_dictionary_map_shift',
149 'value': 'Map::DictionaryMap::kShift' },
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 { 'name': 'bit_field3_number_of_own_descriptors_mask',
151 'value': 'Map::NumberOfOwnDescriptorsBits::kMask' },
152 { 'name': 'bit_field3_number_of_own_descriptors_shift',
153 'value': 'Map::NumberOfOwnDescriptorsBits::kShift' },
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100154
155 { 'name': 'off_fp_context',
156 'value': 'StandardFrameConstants::kContextOffset' },
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 { 'name': 'off_fp_constant_pool',
158 'value': 'StandardFrameConstants::kConstantPoolOffset' },
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100159 { 'name': 'off_fp_marker',
160 'value': 'StandardFrameConstants::kMarkerOffset' },
161 { 'name': 'off_fp_function',
162 'value': 'JavaScriptFrameConstants::kFunctionOffset' },
163 { 'name': 'off_fp_args',
164 'value': 'JavaScriptFrameConstants::kLastParameterOffset' },
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000165
166 { 'name': 'scopeinfo_idx_nparams',
167 'value': 'ScopeInfo::kParameterCount' },
168 { 'name': 'scopeinfo_idx_nstacklocals',
169 'value': 'ScopeInfo::kStackLocalCount' },
170 { 'name': 'scopeinfo_idx_ncontextlocals',
171 'value': 'ScopeInfo::kContextLocalCount' },
172 { 'name': 'scopeinfo_idx_ncontextglobals',
173 'value': 'ScopeInfo::kContextGlobalCount' },
174 { 'name': 'scopeinfo_idx_first_vars',
175 'value': 'ScopeInfo::kVariablePartIndex' },
176
177 { 'name': 'sharedfunctioninfo_start_position_mask',
178 'value': 'SharedFunctionInfo::kStartPositionMask' },
179 { 'name': 'sharedfunctioninfo_start_position_shift',
180 'value': 'SharedFunctionInfo::kStartPositionShift' },
181
182 { 'name': 'jsarray_buffer_was_neutered_mask',
183 'value': 'JSArrayBuffer::WasNeutered::kMask' },
184 { 'name': 'jsarray_buffer_was_neutered_shift',
185 'value': 'JSArrayBuffer::WasNeutered::kShift' },
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100186];
187
188#
189# The following useful fields are missing accessors, so we define fake ones.
190#
191extras_accessors = [
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 'JSFunction, context, Context, kContextOffset',
193 'Context, closure_index, int, CLOSURE_INDEX',
194 'Context, native_context_index, int, NATIVE_CONTEXT_INDEX',
195 'Context, previous_index, int, PREVIOUS_INDEX',
196 'Context, min_context_slots, int, MIN_CONTEXT_SLOTS',
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100197 'HeapObject, map, Map, kMapOffset',
198 'JSObject, elements, Object, kElementsOffset',
199 'FixedArray, data, uintptr_t, kHeaderSize',
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 'JSArrayBuffer, backing_store, Object, kBackingStoreOffset',
201 'JSArrayBufferView, byte_offset, Object, kByteOffsetOffset',
202 'JSTypedArray, length, Object, kLengthOffset',
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100203 'Map, instance_attributes, int, kInstanceAttributesOffset',
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 'Map, inobject_properties_or_constructor_function_index, int, kInObjectPropertiesOrConstructorFunctionIndexOffset',
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100205 'Map, instance_size, int, kInstanceSizeOffset',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206 'Map, bit_field, char, kBitFieldOffset',
207 'Map, bit_field2, char, kBitField2Offset',
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000208 'Map, bit_field3, int, kBitField3Offset',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000209 'Map, prototype, Object, kPrototypeOffset',
210 'NameDictionaryShape, prefix_size, int, kPrefixSize',
211 'NameDictionaryShape, entry_size, int, kEntrySize',
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 'NameDictionary, prefix_start_index, int, kPrefixStartIndex',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 'SeededNumberDictionaryShape, prefix_size, int, kPrefixSize',
214 'UnseededNumberDictionaryShape, prefix_size, int, kPrefixSize',
215 'NumberDictionaryShape, entry_size, int, kEntrySize',
216 'Oddball, kind_offset, int, kKindOffset',
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100217 'HeapNumber, value, double, kValueOffset',
218 'ConsString, first, String, kFirstOffset',
219 'ConsString, second, String, kSecondOffset',
220 'ExternalString, resource, Object, kResourceOffset',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 'SeqOneByteString, chars, char, kHeaderSize',
222 'SeqTwoByteString, chars, char, kHeaderSize',
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100223 'SharedFunctionInfo, code, Code, kCodeOffset',
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 'SharedFunctionInfo, scope_info, ScopeInfo, kScopeInfoOffset',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 'SlicedString, parent, String, kParentOffset',
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100226 'Code, instruction_start, uintptr_t, kHeaderSize',
227 'Code, instruction_size, int, kInstructionSizeOffset',
228];
229
230#
231# The following is a whitelist of classes we expect to find when scanning the
232# source code. This list is not exhaustive, but it's still useful to identify
233# when this script gets out of sync with the source. See load_objects().
234#
235expected_classes = [
236 'ConsString', 'FixedArray', 'HeapNumber', 'JSArray', 'JSFunction',
237 'JSObject', 'JSRegExp', 'JSValue', 'Map', 'Oddball', 'Script',
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 'SeqOneByteString', 'SharedFunctionInfo'
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100239];
240
241
242#
243# The following structures store high-level representations of the structures
244# for which we're going to emit descriptive constants.
245#
246types = {}; # set of all type names
247typeclasses = {}; # maps type names to corresponding class names
248klasses = {}; # known classes, including parents
249fields = []; # field declarations
250
251header = '''
252/*
253 * This file is generated by %s. Do not edit directly.
254 */
255
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256#include "src/v8.h"
257#include "src/frames.h"
258#include "src/frames-inl.h" /* for architecture-specific frame constants */
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100259
260using namespace v8::internal;
261
262extern "C" {
263
264/* stack frame constants */
265#define FRAME_CONST(value, klass) \
266 int v8dbg_frametype_##klass = StackFrame::value;
267
268STACK_FRAME_TYPE_LIST(FRAME_CONST)
269
270#undef FRAME_CONST
271
272''' % sys.argv[0];
273
274footer = '''
275}
276'''
277
278#
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279# Get the base class
280#
281def get_base_class(klass):
282 if (klass == 'Object'):
283 return klass;
284
285 if (not (klass in klasses)):
286 return None;
287
288 k = klasses[klass];
289
290 return get_base_class(k['parent']);
291
292#
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100293# Loads class hierarchy and type information from "objects.h".
294#
295def load_objects():
296 objfilename = sys.argv[2];
297 objfile = open(objfilename, 'r');
298 in_insttype = False;
299
300 typestr = '';
301
302 #
303 # Construct a dictionary for the classes we're sure should be present.
304 #
305 checktypes = {};
306 for klass in expected_classes:
307 checktypes[klass] = True;
308
309 #
310 # Iterate objects.h line-by-line to collect type and class information.
311 # For types, we accumulate a string representing the entire InstanceType
312 # enum definition and parse it later because it's easier to do so
313 # without the embedded newlines.
314 #
315 for line in objfile:
316 if (line.startswith('enum InstanceType {')):
317 in_insttype = True;
318 continue;
319
320 if (in_insttype and line.startswith('};')):
321 in_insttype = False;
322 continue;
323
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 line = re.sub('//.*', '', line.strip());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100325
326 if (in_insttype):
327 typestr += line;
328 continue;
329
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 match = re.match('class (\w[^:]*)(: public (\w[^{]*))?\s*{\s*',
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100331 line);
332
333 if (match):
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000334 klass = match.group(1).strip();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100335 pklass = match.group(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 if (pklass):
337 pklass = pklass.strip();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100338 klasses[klass] = { 'parent': pklass };
339
340 #
341 # Process the instance type declaration.
342 #
343 entries = typestr.split(',');
344 for entry in entries:
345 types[re.sub('\s*=.*', '', entry).lstrip()] = True;
346
347 #
348 # Infer class names for each type based on a systematic transformation.
349 # For example, "JS_FUNCTION_TYPE" becomes "JSFunction". We find the
350 # class for each type rather than the other way around because there are
351 # fewer cases where one type maps to more than one class than the other
352 # way around.
353 #
354 for type in types:
355 #
356 # Symbols and Strings are implemented using the same classes.
357 #
358 usetype = re.sub('SYMBOL_', 'STRING_', type);
359
360 #
361 # REGEXP behaves like REG_EXP, as in JS_REGEXP_TYPE => JSRegExp.
362 #
363 usetype = re.sub('_REGEXP_', '_REG_EXP_', usetype);
364
365 #
366 # Remove the "_TYPE" suffix and then convert to camel case,
367 # except that a "JS" prefix remains uppercase (as in
368 # "JS_FUNCTION_TYPE" => "JSFunction").
369 #
370 if (not usetype.endswith('_TYPE')):
371 continue;
372
373 usetype = usetype[0:len(usetype) - len('_TYPE')];
374 parts = usetype.split('_');
375 cctype = '';
376
377 if (parts[0] == 'JS'):
378 cctype = 'JS';
379 start = 1;
380 else:
381 cctype = '';
382 start = 0;
383
384 for ii in range(start, len(parts)):
385 part = parts[ii];
386 cctype += part[0].upper() + part[1:].lower();
387
388 #
389 # Mapping string types is more complicated. Both types and
390 # class names for Strings specify a representation (e.g., Seq,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000391 # Cons, External, or Sliced) and an encoding (TwoByte/OneByte),
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100392 # In the simplest case, both of these are explicit in both
393 # names, as in:
394 #
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 # EXTERNAL_ONE_BYTE_STRING_TYPE => ExternalOneByteString
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100396 #
397 # However, either the representation or encoding can be omitted
398 # from the type name, in which case "Seq" and "TwoByte" are
399 # assumed, as in:
400 #
401 # STRING_TYPE => SeqTwoByteString
402 #
403 # Additionally, sometimes the type name has more information
404 # than the class, as in:
405 #
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000406 # CONS_ONE_BYTE_STRING_TYPE => ConsString
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100407 #
408 # To figure this out dynamically, we first check for a
409 # representation and encoding and add them if they're not
410 # present. If that doesn't yield a valid class name, then we
411 # strip out the representation.
412 #
413 if (cctype.endswith('String')):
414 if (cctype.find('Cons') == -1 and
415 cctype.find('External') == -1 and
416 cctype.find('Sliced') == -1):
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000417 if (cctype.find('OneByte') != -1):
418 cctype = re.sub('OneByteString$',
419 'SeqOneByteString', cctype);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100420 else:
421 cctype = re.sub('String$',
422 'SeqString', cctype);
423
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000424 if (cctype.find('OneByte') == -1):
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100425 cctype = re.sub('String$', 'TwoByteString',
426 cctype);
427
428 if (not (cctype in klasses)):
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429 cctype = re.sub('OneByte', '', cctype);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100430 cctype = re.sub('TwoByte', '', cctype);
431
432 #
433 # Despite all that, some types have no corresponding class.
434 #
435 if (cctype in klasses):
436 typeclasses[type] = cctype;
437 if (cctype in checktypes):
438 del checktypes[cctype];
439
440 if (len(checktypes) > 0):
441 for klass in checktypes:
442 print('error: expected class \"%s\" not found' % klass);
443
444 sys.exit(1);
445
446
447#
448# For a given macro call, pick apart the arguments and return an object
449# describing the corresponding output constant. See load_fields().
450#
451def parse_field(call):
452 # Replace newlines with spaces.
453 for ii in range(0, len(call)):
454 if (call[ii] == '\n'):
455 call[ii] == ' ';
456
457 idx = call.find('(');
458 kind = call[0:idx];
459 rest = call[idx + 1: len(call) - 1];
460 args = re.split('\s*,\s*', rest);
461
462 consts = [];
463
464 if (kind == 'ACCESSORS' or kind == 'ACCESSORS_GCSAFE'):
465 klass = args[0];
466 field = args[1];
467 dtype = args[2];
468 offset = args[3];
469
470 return ({
471 'name': 'class_%s__%s__%s' % (klass, field, dtype),
472 'value': '%s::%s' % (klass, offset)
473 });
474
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000475 assert(kind == 'SMI_ACCESSORS' or kind == 'ACCESSORS_TO_SMI');
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100476 klass = args[0];
477 field = args[1];
478 offset = args[2];
479
480 return ({
481 'name': 'class_%s__%s__%s' % (klass, field, 'SMI'),
482 'value': '%s::%s' % (klass, offset)
483 });
484
485#
486# Load field offset information from objects-inl.h.
487#
488def load_fields():
489 inlfilename = sys.argv[3];
490 inlfile = open(inlfilename, 'r');
491
492 #
493 # Each class's fields and the corresponding offsets are described in the
494 # source by calls to macros like "ACCESSORS" (and friends). All we do
495 # here is extract these macro invocations, taking into account that they
496 # may span multiple lines and may contain nested parentheses. We also
497 # call parse_field() to pick apart the invocation.
498 #
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 prefixes = [ 'ACCESSORS', 'ACCESSORS_GCSAFE',
500 'SMI_ACCESSORS', 'ACCESSORS_TO_SMI' ];
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100501 current = '';
502 opens = 0;
503
504 for line in inlfile:
505 if (opens > 0):
506 # Continuation line
507 for ii in range(0, len(line)):
508 if (line[ii] == '('):
509 opens += 1;
510 elif (line[ii] == ')'):
511 opens -= 1;
512
513 if (opens == 0):
514 break;
515
516 current += line[0:ii + 1];
517 continue;
518
519 for prefix in prefixes:
520 if (not line.startswith(prefix + '(')):
521 continue;
522
523 if (len(current) > 0):
524 fields.append(parse_field(current));
525 current = '';
526
527 for ii in range(len(prefix), len(line)):
528 if (line[ii] == '('):
529 opens += 1;
530 elif (line[ii] == ')'):
531 opens -= 1;
532
533 if (opens == 0):
534 break;
535
536 current += line[0:ii + 1];
537
538 if (len(current) > 0):
539 fields.append(parse_field(current));
540 current = '';
541
542 for body in extras_accessors:
543 fields.append(parse_field('ACCESSORS(%s)' % body));
544
545#
546# Emit a block of constants.
547#
548def emit_set(out, consts):
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000549 # Fix up overzealous parses. This could be done inside the
550 # parsers but as there are several, it's easiest to do it here.
551 ws = re.compile('\s+')
552 for const in consts:
553 name = ws.sub('', const['name'])
554 value = ws.sub('', str(const['value'])) # Can be a number.
555 out.write('int v8dbg_%s = %s;\n' % (name, value))
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100556 out.write('\n');
557
558#
559# Emit the whole output file.
560#
561def emit_config():
562 out = file(sys.argv[1], 'w');
563
564 out.write(header);
565
566 out.write('/* miscellaneous constants */\n');
567 emit_set(out, consts_misc);
568
569 out.write('/* class type information */\n');
570 consts = [];
571 keys = typeclasses.keys();
572 keys.sort();
573 for typename in keys:
574 klass = typeclasses[typename];
575 consts.append({
576 'name': 'type_%s__%s' % (klass, typename),
577 'value': typename
578 });
579
580 emit_set(out, consts);
581
582 out.write('/* class hierarchy information */\n');
583 consts = [];
584 keys = klasses.keys();
585 keys.sort();
586 for klassname in keys:
587 pklass = klasses[klassname]['parent'];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588 bklass = get_base_class(klassname);
589 if (bklass != 'Object'):
590 continue;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100591 if (pklass == None):
592 continue;
593
594 consts.append({
595 'name': 'parent_%s__%s' % (klassname, pklass),
596 'value': 0
597 });
598
599 emit_set(out, consts);
600
601 out.write('/* field information */\n');
602 emit_set(out, fields);
603
604 out.write(footer);
605
606if (len(sys.argv) < 4):
607 print('usage: %s output.cc objects.h objects-inl.h' % sys.argv[0]);
608 sys.exit(2);
609
610load_objects();
611load_fields();
612emit_config();