Line data Source code
1 : // Copyright 2017 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/parsing/preparse-data.h"
6 :
7 : #include <vector>
8 :
9 : #include "src/ast/scopes.h"
10 : #include "src/ast/variables.h"
11 : #include "src/handles.h"
12 : #include "src/objects-inl.h"
13 : #include "src/objects/shared-function-info.h"
14 : #include "src/parsing/parser.h"
15 : #include "src/parsing/preparse-data-impl.h"
16 : #include "src/parsing/preparser.h"
17 : #include "src/zone/zone-list-inl.h" // crbug.com/v8/8816
18 :
19 : namespace v8 {
20 : namespace internal {
21 :
22 : namespace {
23 :
24 : class ScopeCallsSloppyEvalField : public BitField8<bool, 0, 1> {};
25 : class InnerScopeCallsEvalField
26 : : public BitField8<bool, ScopeCallsSloppyEvalField::kNext, 1> {};
27 :
28 : class VariableMaybeAssignedField : public BitField8<bool, 0, 1> {};
29 : class VariableContextAllocatedField
30 : : public BitField8<bool, VariableMaybeAssignedField::kNext, 1> {};
31 :
32 : class HasDataField : public BitField<bool, 0, 1> {};
33 : class LengthEqualsParametersField
34 : : public BitField<bool, HasDataField::kNext, 1> {};
35 : class NumberOfParametersField
36 : : public BitField<uint16_t, LengthEqualsParametersField::kNext, 16> {};
37 :
38 : class LanguageField : public BitField8<LanguageMode, 0, 1> {};
39 : class UsesSuperField : public BitField8<bool, LanguageField::kNext, 1> {};
40 : STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
41 :
42 : } // namespace
43 :
44 : /*
45 :
46 : Internal data format for the backing store of PreparseDataBuilder and
47 : PreparseData::scope_data (on the heap):
48 :
49 : (Skippable function data:)
50 : ------------------------------------
51 : | scope_data_start (debug only) |
52 : ------------------------------------
53 : | data for inner function n |
54 : | ... |
55 : ------------------------------------
56 : | data for inner function 1 |
57 : | ... |
58 : ------------------------------------
59 : (Scope allocation data:) << scope_data_start points here in debug
60 : ------------------------------------
61 : magic value (debug only)
62 : ------------------------------------
63 : scope positions (debug only)
64 : ------------------------------------
65 : | scope type << only in debug |
66 : | eval |
67 : | ---------------------- |
68 : | | data for variables | |
69 : | | ... | |
70 : | ---------------------- |
71 : ------------------------------------
72 : ------------------------------------
73 : | data for inner scope m | << but not for function scopes
74 : | ... |
75 : ------------------------------------
76 : ...
77 : ------------------------------------
78 : | data for inner scope 1 |
79 : | ... |
80 : ------------------------------------
81 :
82 : PreparseData::child_data is an array of PreparseData objects, one
83 : for each skippable inner function.
84 :
85 : ConsumedPreparseData wraps a PreparseData and reads data from it.
86 :
87 : */
88 :
89 0 : PreparseDataBuilder::PreparseDataBuilder(Zone* zone,
90 : PreparseDataBuilder* parent_builder,
91 : std::vector<void*>* children_buffer)
92 : : parent_(parent_builder),
93 : byte_data_(),
94 : children_buffer_(children_buffer),
95 : function_scope_(nullptr),
96 : function_length_(-1),
97 : num_inner_functions_(0),
98 : num_inner_with_data_(0),
99 : bailed_out_(false),
100 5364618 : has_data_(false) {}
101 :
102 2682309 : void PreparseDataBuilder::DataGatheringScope::Start(
103 : DeclarationScope* function_scope) {
104 2682309 : Zone* main_zone = preparser_->main_zone();
105 : builder_ = new (main_zone)
106 : PreparseDataBuilder(main_zone, preparser_->preparse_data_builder(),
107 2682309 : preparser_->preparse_data_builder_buffer());
108 2682309 : preparser_->set_preparse_data_builder(builder_);
109 2682309 : function_scope->set_preparse_data_builder(builder_);
110 2682309 : }
111 :
112 2682269 : void PreparseDataBuilder::DataGatheringScope::Close() {
113 2682269 : PreparseDataBuilder* parent = builder_->parent_;
114 2682269 : preparser_->set_preparse_data_builder(parent);
115 2682269 : builder_->FinalizeChildren(preparser_->main_zone());
116 :
117 2682317 : if (parent == nullptr) return;
118 296888 : if (!builder_->HasDataForParent()) return;
119 : parent->AddChild(builder_);
120 : }
121 :
122 5 : void PreparseDataBuilder::ByteData::Start(std::vector<uint8_t>* buffer) {
123 : DCHECK(!is_finalized_);
124 96075 : byte_data_ = buffer;
125 : DCHECK_EQ(byte_data_->size(), 0);
126 : DCHECK_EQ(index_, 0);
127 5 : }
128 :
129 96076 : void PreparseDataBuilder::ByteData::Finalize(Zone* zone) {
130 : uint8_t* raw_zone_data =
131 96076 : static_cast<uint8_t*>(ZoneAllocationPolicy(zone).New(index_));
132 96077 : memcpy(raw_zone_data, byte_data_->data(), index_);
133 96077 : byte_data_->resize(0);
134 96079 : zone_byte_data_ = Vector<uint8_t>(raw_zone_data, index_);
135 : #ifdef DEBUG
136 : is_finalized_ = true;
137 : #endif
138 96079 : }
139 :
140 936871 : void PreparseDataBuilder::ByteData::Reserve(size_t bytes) {
141 : // Make sure we have at least {bytes} capacity left in the buffer_.
142 : DCHECK_LE(length(), byte_data_->size());
143 1873742 : size_t capacity = byte_data_->size() - length();
144 936871 : if (capacity >= bytes) return;
145 137053 : size_t delta = bytes - capacity;
146 274104 : byte_data_->insert(byte_data_->end(), delta, 0);
147 : }
148 :
149 936876 : int PreparseDataBuilder::ByteData::length() const { return index_; }
150 :
151 0 : void PreparseDataBuilder::ByteData::Add(uint8_t byte) {
152 : DCHECK_LE(0, index_);
153 : DCHECK_LT(index_, byte_data_->size());
154 2817870 : (*byte_data_)[index_++] = byte;
155 0 : }
156 :
157 : #ifdef DEBUG
158 : void PreparseDataBuilder::ByteData::WriteUint32(uint32_t data) {
159 : DCHECK(!is_finalized_);
160 : Add(kUint32Size);
161 : Add(data & 0xFF);
162 : Add((data >> 8) & 0xFF);
163 : Add((data >> 16) & 0xFF);
164 : Add((data >> 24) & 0xFF);
165 : free_quarters_in_last_byte_ = 0;
166 : }
167 :
168 : void PreparseDataBuilder::ByteData::SaveCurrentSizeAtFirstUint32() {
169 : int current_length = length();
170 : index_ = 0;
171 : CHECK_EQ(byte_data_->at(0), kUint32Size);
172 : WriteUint32(current_length);
173 : index_ = current_length;
174 : }
175 : #endif
176 :
177 25 : void PreparseDataBuilder::ByteData::WriteVarint32(uint32_t data) {
178 : #ifdef DEBUG
179 : // Save expected item size in debug mode.
180 : Add(kVarint32MinSize);
181 : #endif
182 : // See ValueSerializer::WriteVarint.
183 822038 : do {
184 822038 : uint8_t next_byte = (data & 0x7F);
185 822038 : data >>= 7;
186 : // Add continue bit.
187 822038 : if (data) next_byte |= 0x80;
188 : Add(next_byte & 0xFF);
189 : } while (data);
190 : #ifdef DEBUG
191 : Add(kVarint32EndMarker);
192 : #endif
193 571290 : free_quarters_in_last_byte_ = 0;
194 25 : }
195 :
196 25 : void PreparseDataBuilder::ByteData::WriteUint8(uint8_t data) {
197 : DCHECK(!is_finalized_);
198 : #ifdef DEBUG
199 : // Save expected item size in debug mode.
200 : Add(kUint8Size);
201 : #endif
202 : Add(data);
203 218626 : free_quarters_in_last_byte_ = 0;
204 25 : }
205 :
206 764911 : void PreparseDataBuilder::ByteData::WriteQuarter(uint8_t data) {
207 : DCHECK(!is_finalized_);
208 : DCHECK_LE(data, 3);
209 764911 : if (free_quarters_in_last_byte_ == 0) {
210 : #ifdef DEBUG
211 : // Save a marker in debug mode.
212 : Add(kQuarterMarker);
213 : #endif
214 : Add(0);
215 368271 : free_quarters_in_last_byte_ = 3;
216 : } else {
217 396640 : --free_quarters_in_last_byte_;
218 : }
219 :
220 764911 : uint8_t shift_amount = free_quarters_in_last_byte_ * 2;
221 : DCHECK_EQ(byte_data_->at(index_ - 1) & (3 << shift_amount), 0);
222 1529822 : (*byte_data_)[index_ - 1] |= (data << shift_amount);
223 764911 : }
224 :
225 148438 : void PreparseDataBuilder::DataGatheringScope::SetSkippableFunction(
226 : DeclarationScope* function_scope, int function_length,
227 : int num_inner_functions) {
228 : DCHECK_NULL(builder_->function_scope_);
229 148438 : builder_->function_scope_ = function_scope;
230 : DCHECK_EQ(builder_->num_inner_functions_, 0);
231 148438 : builder_->function_length_ = function_length;
232 148438 : builder_->num_inner_functions_ = num_inner_functions;
233 148438 : builder_->parent_->has_data_ = true;
234 148438 : }
235 :
236 631751 : bool PreparseDataBuilder::HasInnerFunctions() const {
237 631751 : return !children_.empty();
238 : }
239 :
240 2868463 : bool PreparseDataBuilder::HasData() const { return !bailed_out_ && has_data_; }
241 :
242 0 : bool PreparseDataBuilder::HasDataForParent() const {
243 148444 : return HasData() || function_scope_ != nullptr;
244 : }
245 :
246 0 : void PreparseDataBuilder::AddChild(PreparseDataBuilder* child) {
247 : DCHECK(!finalized_children_);
248 : children_buffer_.Add(child);
249 0 : }
250 :
251 2682263 : void PreparseDataBuilder::FinalizeChildren(Zone* zone) {
252 : DCHECK(!finalized_children_);
253 2682263 : Vector<PreparseDataBuilder*> children = children_buffer_.CopyTo(zone);
254 : children_buffer_.Rewind();
255 2682308 : children_ = children;
256 : #ifdef DEBUG
257 : finalized_children_ = true;
258 : #endif
259 2682308 : }
260 :
261 429802 : bool PreparseDataBuilder::ScopeNeedsData(Scope* scope) {
262 429802 : if (scope->is_function_scope()) {
263 : // Default constructors don't need data (they cannot contain inner functions
264 : // defined by the user). Other functions do.
265 637699 : return !IsDefaultConstructor(scope->AsDeclarationScope()->function_kind());
266 : }
267 110953 : if (!scope->is_hidden()) {
268 99245 : for (Variable* var : *scope->locals()) {
269 72263 : if (IsDeclaredVariableMode(var->mode())) return true;
270 : }
271 : }
272 62518 : for (Scope* inner = scope->inner_scope(); inner != nullptr;
273 : inner = inner->sibling()) {
274 26680 : if (ScopeNeedsData(inner)) return true;
275 : }
276 : return false;
277 : }
278 :
279 142651 : bool PreparseDataBuilder::SaveDataForSkippableFunction(
280 : PreparseDataBuilder* builder) {
281 142651 : DeclarationScope* function_scope = builder->function_scope_;
282 : // Start position is used for a sanity check when consuming the data, we could
283 : // remove it in the future if we're very pressed for space but it's been good
284 : // at catching bugs in the wild so far.
285 142651 : byte_data_.WriteVarint32(function_scope->start_position());
286 142651 : byte_data_.WriteVarint32(function_scope->end_position());
287 :
288 : bool has_data = builder->HasData();
289 : bool length_equals_parameters =
290 142651 : function_scope->num_parameters() == builder->function_length_;
291 : uint32_t has_data_and_num_parameters =
292 142651 : HasDataField::encode(has_data) |
293 : LengthEqualsParametersField::encode(length_equals_parameters) |
294 142651 : NumberOfParametersField::encode(function_scope->num_parameters());
295 : byte_data_.WriteVarint32(has_data_and_num_parameters);
296 142651 : if (!length_equals_parameters) {
297 661 : byte_data_.WriteVarint32(builder->function_length_);
298 : }
299 142651 : byte_data_.WriteVarint32(builder->num_inner_functions_);
300 :
301 : uint8_t language_and_super =
302 : LanguageField::encode(function_scope->language_mode()) |
303 285302 : UsesSuperField::encode(function_scope->NeedsHomeObject());
304 142651 : byte_data_.WriteQuarter(language_and_super);
305 142651 : return has_data;
306 : }
307 :
308 2051713 : void PreparseDataBuilder::SaveScopeAllocationData(DeclarationScope* scope,
309 : Parser* parser) {
310 2051713 : if (!has_data_) return;
311 : DCHECK(HasInnerFunctions());
312 :
313 : byte_data_.Start(parser->preparse_data_buffer());
314 :
315 : #ifdef DEBUG
316 : // Reserve Uint32 for scope_data_start debug info.
317 : byte_data_.Reserve(kUint32Size);
318 : byte_data_.WriteUint32(0);
319 : #endif
320 96070 : byte_data_.Reserve(children_.size() * kSkippableFunctionMaxDataSize);
321 : DCHECK(finalized_children_);
322 381374 : for (const auto& builder : children_) {
323 : // Keep track of functions with inner data. {children_} contains also the
324 : // builders that have no inner functions at all.
325 142651 : if (SaveDataForSkippableFunction(builder)) num_inner_with_data_++;
326 : }
327 :
328 : // Don't save imcoplete scope information when bailed out.
329 96071 : if (!bailed_out_) {
330 : #ifdef DEBUG
331 : // function data items, kSkippableMinFunctionDataSize each.
332 : CHECK_GE(byte_data_.length(), kPlaceholderSize);
333 : CHECK_LE(byte_data_.length(), std::numeric_limits<uint32_t>::max());
334 :
335 : byte_data_.SaveCurrentSizeAtFirstUint32();
336 : // For a data integrity check, write a value between data about skipped inner
337 : // funcs and data about variables.
338 : byte_data_.Reserve(kUint32Size * 3);
339 : byte_data_.WriteUint32(kMagicValue);
340 : byte_data_.WriteUint32(scope->start_position());
341 : byte_data_.WriteUint32(scope->end_position());
342 : #endif
343 :
344 95914 : if (ScopeNeedsData(scope)) SaveDataForScope(scope);
345 : }
346 96070 : byte_data_.Finalize(parser->factory()->zone());
347 : }
348 :
349 218599 : void PreparseDataBuilder::SaveDataForScope(Scope* scope) {
350 : DCHECK_NE(scope->end_position(), kNoSourcePosition);
351 : DCHECK(ScopeNeedsData(scope));
352 :
353 : #ifdef DEBUG
354 : byte_data_.Reserve(kUint8Size);
355 : byte_data_.WriteUint8(scope->scope_type());
356 : #endif
357 :
358 : uint8_t eval =
359 : ScopeCallsSloppyEvalField::encode(
360 398836 : scope->is_declaration_scope() &&
361 180236 : scope->AsDeclarationScope()->calls_sloppy_eval()) |
362 218600 : InnerScopeCallsEvalField::encode(scope->inner_scope_calls_eval());
363 218600 : byte_data_.Reserve(kUint8Size);
364 : byte_data_.WriteUint8(eval);
365 :
366 218601 : if (scope->is_function_scope()) {
367 178356 : Variable* function = scope->AsDeclarationScope()->function_var();
368 178356 : if (function != nullptr) SaveDataForVariable(function);
369 : }
370 :
371 833432 : for (Variable* var : *scope->locals()) {
372 614827 : if (IsDeclaredVariableMode(var->mode())) SaveDataForVariable(var);
373 : }
374 :
375 218605 : SaveDataForInnerScopes(scope);
376 218605 : }
377 :
378 622191 : void PreparseDataBuilder::SaveDataForVariable(Variable* var) {
379 : #ifdef DEBUG
380 : // Store the variable name in debug mode; this way we can check that we
381 : // restore data to the correct variable.
382 : const AstRawString* name = var->raw_name();
383 : byte_data_.Reserve(kUint32Size + (name->length() + 1) * kUint8Size);
384 : byte_data_.WriteUint8(name->is_one_byte());
385 : byte_data_.WriteUint32(name->length());
386 : for (int i = 0; i < name->length(); ++i) {
387 : byte_data_.WriteUint8(name->raw_data()[i]);
388 : }
389 : #endif
390 :
391 622191 : byte variable_data = VariableMaybeAssignedField::encode(
392 : var->maybe_assigned() == kMaybeAssigned) |
393 : VariableContextAllocatedField::encode(
394 622191 : var->has_forced_context_allocation());
395 622191 : byte_data_.Reserve(kUint8Size);
396 622195 : byte_data_.WriteQuarter(variable_data);
397 622193 : }
398 :
399 218601 : void PreparseDataBuilder::SaveDataForInnerScopes(Scope* scope) {
400 : // Inner scopes are stored in the reverse order, but we'd like to write the
401 : // data in the logical order. There might be many inner scopes, so we don't
402 : // want to recurse here.
403 779069 : for (Scope* inner = scope->inner_scope(); inner != nullptr;
404 : inner = inner->sibling()) {
405 280230 : if (inner->IsSkippableFunctionScope()) {
406 : // Don't save data about function scopes, since they'll have their own
407 : // PreparseDataBuilder where their data is saved.
408 : DCHECK_NOT_NULL(inner->AsDeclarationScope()->preparse_data_builder());
409 : continue;
410 : }
411 137813 : if (!ScopeNeedsData(inner)) continue;
412 122690 : SaveDataForScope(inner);
413 : }
414 218605 : }
415 :
416 :
417 63709 : Handle<PreparseData> PreparseDataBuilder::ByteData::CopyToHeap(
418 : Isolate* isolate, int children_length) {
419 : DCHECK(is_finalized_);
420 : int data_length = zone_byte_data_.length();
421 : Handle<PreparseData> data =
422 63709 : isolate->factory()->NewPreparseData(data_length, children_length);
423 : data->copy_in(0, zone_byte_data_.start(), data_length);
424 63709 : return data;
425 : }
426 :
427 63704 : Handle<PreparseData> PreparseDataBuilder::Serialize(Isolate* isolate) {
428 : DCHECK(HasData());
429 : DCHECK(!ThisOrParentBailedOut());
430 : Handle<PreparseData> data =
431 63704 : byte_data_.CopyToHeap(isolate, num_inner_with_data_);
432 : int i = 0;
433 : DCHECK(finalized_children_);
434 258444 : for (const auto& builder : children_) {
435 285262 : if (!builder->HasData()) continue;
436 6848 : Handle<PreparseData> child_data = builder->Serialize(isolate);
437 13696 : data->set_child(i++, *child_data);
438 : }
439 : DCHECK_EQ(i, data->children_length());
440 63704 : return data;
441 : }
442 :
443 10 : ZonePreparseData* PreparseDataBuilder::Serialize(Zone* zone) {
444 : DCHECK(HasData());
445 : DCHECK(!ThisOrParentBailedOut());
446 10 : ZonePreparseData* data = byte_data_.CopyToZone(zone, num_inner_with_data_);
447 : int i = 0;
448 : DCHECK(finalized_children_);
449 450 : for (const auto& builder : children_) {
450 440 : if (!builder->HasData()) continue;
451 0 : ZonePreparseData* child = builder->Serialize(zone);
452 0 : data->set_child(i++, child);
453 : }
454 : DCHECK_EQ(i, data->children_length());
455 10 : return data;
456 : }
457 :
458 : class BuilderProducedPreparseData final : public ProducedPreparseData {
459 : public:
460 : explicit BuilderProducedPreparseData(PreparseDataBuilder* builder)
461 84613 : : builder_(builder) {
462 : DCHECK(builder->HasData());
463 : }
464 :
465 56856 : Handle<PreparseData> Serialize(Isolate* isolate) final {
466 56856 : return builder_->Serialize(isolate);
467 : }
468 :
469 10 : ZonePreparseData* Serialize(Zone* zone) final {
470 10 : return builder_->Serialize(zone);
471 : }
472 :
473 : private:
474 : PreparseDataBuilder* builder_;
475 : };
476 :
477 : class OnHeapProducedPreparseData final : public ProducedPreparseData {
478 : public:
479 : explicit OnHeapProducedPreparseData(Handle<PreparseData> data)
480 3197 : : data_(data) {}
481 :
482 2802 : Handle<PreparseData> Serialize(Isolate* isolate) final {
483 : DCHECK(!data_->is_null());
484 2802 : return data_;
485 : }
486 :
487 0 : ZonePreparseData* Serialize(Zone* zone) final {
488 : // Not required.
489 0 : UNREACHABLE();
490 : }
491 :
492 : private:
493 : Handle<PreparseData> data_;
494 : };
495 :
496 : class ZoneProducedPreparseData final : public ProducedPreparseData {
497 : public:
498 0 : explicit ZoneProducedPreparseData(ZonePreparseData* data) : data_(data) {}
499 :
500 0 : Handle<PreparseData> Serialize(Isolate* isolate) final {
501 0 : return data_->Serialize(isolate);
502 : }
503 :
504 0 : ZonePreparseData* Serialize(Zone* zone) final { return data_; }
505 :
506 : private:
507 : ZonePreparseData* data_;
508 : };
509 :
510 84614 : ProducedPreparseData* ProducedPreparseData::For(PreparseDataBuilder* builder,
511 : Zone* zone) {
512 84613 : return new (zone) BuilderProducedPreparseData(builder);
513 : }
514 :
515 0 : ProducedPreparseData* ProducedPreparseData::For(Handle<PreparseData> data,
516 : Zone* zone) {
517 0 : return new (zone) OnHeapProducedPreparseData(data);
518 : }
519 :
520 0 : ProducedPreparseData* ProducedPreparseData::For(ZonePreparseData* data,
521 : Zone* zone) {
522 0 : return new (zone) ZoneProducedPreparseData(data);
523 : }
524 :
525 : template <class Data>
526 : ProducedPreparseData*
527 60791 : BaseConsumedPreparseData<Data>::GetDataForSkippableFunction(
528 : Zone* zone, int start_position, int* end_position, int* num_parameters,
529 : int* function_length, int* num_inner_functions, bool* uses_super_property,
530 : LanguageMode* language_mode) {
531 : // The skippable function *must* be the next function in the data. Use the
532 : // start position as a sanity check.
533 : typename ByteData::ReadingScope reading_scope(this);
534 60791 : CHECK(scope_data_->HasRemainingBytes(
535 : PreparseByteDataConstants::kSkippableFunctionMinDataSize));
536 219 : int start_position_from_data = scope_data_->ReadVarint32();
537 60791 : CHECK_EQ(start_position, start_position_from_data);
538 60791 : *end_position = scope_data_->ReadVarint32();
539 : DCHECK_GT(*end_position, start_position);
540 :
541 60791 : uint32_t has_data_and_num_parameters = scope_data_->ReadVarint32();
542 : bool has_data = HasDataField::decode(has_data_and_num_parameters);
543 60791 : *num_parameters =
544 : NumberOfParametersField::decode(has_data_and_num_parameters);
545 : bool length_equals_parameters =
546 : LengthEqualsParametersField::decode(has_data_and_num_parameters);
547 60791 : if (length_equals_parameters) {
548 60737 : *function_length = *num_parameters;
549 : } else {
550 54 : *function_length = scope_data_->ReadVarint32();
551 : }
552 60791 : *num_inner_functions = scope_data_->ReadVarint32();
553 :
554 219 : uint8_t language_and_super = scope_data_->ReadQuarter();
555 60791 : *language_mode = LanguageMode(LanguageField::decode(language_and_super));
556 60791 : *uses_super_property = UsesSuperField::decode(language_and_super);
557 :
558 60791 : if (!has_data) return nullptr;
559 :
560 : // Retrieve the corresponding PreparseData and associate it to the
561 : // skipped function. If the skipped functions contains inner functions, those
562 : // can be skipped when the skipped function is eagerly parsed.
563 3197 : return GetChildData(zone, child_index_++);
564 : }
565 :
566 : template <class Data>
567 36542 : void BaseConsumedPreparseData<Data>::RestoreScopeAllocationData(
568 : DeclarationScope* scope) {
569 : DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
570 : typename ByteData::ReadingScope reading_scope(this);
571 :
572 : #ifdef DEBUG
573 : int magic_value_from_data = scope_data_->ReadUint32();
574 : // Check that we've consumed all inner function data.
575 : DCHECK_EQ(magic_value_from_data, ByteData::kMagicValue);
576 :
577 : int start_position_from_data = scope_data_->ReadUint32();
578 : int end_position_from_data = scope_data_->ReadUint32();
579 : DCHECK_EQ(start_position_from_data, scope->start_position());
580 : DCHECK_EQ(end_position_from_data, scope->end_position());
581 : #endif
582 :
583 36542 : RestoreDataForScope(scope);
584 :
585 : // Check that we consumed all scope data.
586 : DCHECK_EQ(scope_data_->RemainingBytes(), 0);
587 36542 : }
588 :
589 : template <typename Data>
590 164599 : void BaseConsumedPreparseData<Data>::RestoreDataForScope(Scope* scope) {
591 311134 : if (scope->is_declaration_scope() &&
592 146535 : scope->AsDeclarationScope()->is_skipped_function()) {
593 : return;
594 : }
595 :
596 : // It's possible that scope is not present in the data at all (since PreParser
597 : // doesn't create the corresponding scope). In this case, the Scope won't
598 : // contain any variables for which we need the data.
599 103808 : if (!PreparseDataBuilder::ScopeNeedsData(scope)) return;
600 :
601 : // scope_type is stored only in debug mode.
602 : DCHECK_EQ(scope_data_->ReadUint8(), scope->scope_type());
603 :
604 99439 : CHECK(scope_data_->HasRemainingBytes(ByteData::kUint8Size));
605 : uint32_t eval = scope_data_->ReadUint8();
606 99439 : if (ScopeCallsSloppyEvalField::decode(eval)) scope->RecordEvalCall();
607 99439 : if (InnerScopeCallsEvalField::decode(eval)) scope->RecordInnerScopeEvalCall();
608 :
609 99439 : if (scope->is_function_scope()) {
610 80589 : Variable* function = scope->AsDeclarationScope()->function_var();
611 80589 : if (function != nullptr) RestoreDataForVariable(function);
612 : }
613 :
614 334838 : for (Variable* var : *scope->locals()) {
615 235399 : if (IsDeclaredVariableMode(var->mode())) RestoreDataForVariable(var);
616 : }
617 :
618 : RestoreDataForInnerScopes(scope);
619 : }
620 :
621 : template <typename Data>
622 231712 : void BaseConsumedPreparseData<Data>::RestoreDataForVariable(Variable* var) {
623 : #ifdef DEBUG
624 : const AstRawString* name = var->raw_name();
625 : bool data_one_byte = scope_data_->ReadUint8();
626 : DCHECK_IMPLIES(name->is_one_byte(), data_one_byte);
627 : DCHECK_EQ(scope_data_->ReadUint32(), static_cast<uint32_t>(name->length()));
628 : if (!name->is_one_byte() && data_one_byte) {
629 : // It's possible that "name" is a two-byte representation of the string
630 : // stored in the data.
631 : for (int i = 0; i < 2 * name->length(); i += 2) {
632 : #if defined(V8_TARGET_LITTLE_ENDIAN)
633 : DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
634 : DCHECK_EQ(0, name->raw_data()[i + 1]);
635 : #else
636 : DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i + 1]);
637 : DCHECK_EQ(0, name->raw_data()[i]);
638 : #endif // V8_TARGET_LITTLE_ENDIAN
639 : }
640 : } else {
641 : for (int i = 0; i < name->length(); ++i) {
642 : DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
643 : }
644 : }
645 : #endif
646 132 : uint8_t variable_data = scope_data_->ReadQuarter();
647 231712 : if (VariableMaybeAssignedField::decode(variable_data)) {
648 : var->set_maybe_assigned();
649 : }
650 231712 : if (VariableContextAllocatedField::decode(variable_data)) {
651 : var->set_is_used();
652 : var->ForceContextAllocation();
653 : }
654 231712 : }
655 :
656 : template <typename Data>
657 : void BaseConsumedPreparseData<Data>::RestoreDataForInnerScopes(Scope* scope) {
658 227496 : for (Scope* inner = scope->inner_scope(); inner != nullptr;
659 : inner = inner->sibling()) {
660 128057 : RestoreDataForScope(inner);
661 : }
662 : }
663 :
664 : #ifdef DEBUG
665 : template <class Data>
666 : bool BaseConsumedPreparseData<Data>::VerifyDataStart() {
667 : typename ByteData::ReadingScope reading_scope(this);
668 : // The first uint32 contains the size of the skippable function data.
669 : int scope_data_start = scope_data_->ReadUint32();
670 : scope_data_->SetPosition(scope_data_start);
671 : CHECK_EQ(scope_data_->ReadUint32(), ByteData::kMagicValue);
672 : // The first data item is scope_data_start. Skip over it.
673 : scope_data_->SetPosition(ByteData::kPlaceholderSize);
674 : return true;
675 : }
676 : #endif
677 :
678 194210 : PreparseData OnHeapConsumedPreparseData::GetScopeData() { return *data_; }
679 :
680 3197 : ProducedPreparseData* OnHeapConsumedPreparseData::GetChildData(Zone* zone,
681 : int index) {
682 : DisallowHeapAllocation no_gc;
683 9591 : Handle<PreparseData> child_data_handle(data_->get_child(index), isolate_);
684 3197 : return ProducedPreparseData::For(child_data_handle, zone);
685 : }
686 :
687 0 : OnHeapConsumedPreparseData::OnHeapConsumedPreparseData(
688 : Isolate* isolate, Handle<PreparseData> data)
689 36738 : : BaseConsumedPreparseData<PreparseData>(), isolate_(isolate), data_(data) {
690 : DCHECK_NOT_NULL(isolate);
691 : DCHECK(data->IsPreparseData());
692 : DCHECK(VerifyDataStart());
693 0 : }
694 :
695 15 : ZonePreparseData::ZonePreparseData(Zone* zone, Vector<uint8_t>* byte_data,
696 : int children_length)
697 : : byte_data_(byte_data->begin(), byte_data->end(), zone),
698 30 : children_(children_length, zone) {}
699 :
700 0 : Handle<PreparseData> ZonePreparseData::Serialize(Isolate* isolate) {
701 0 : int data_size = static_cast<int>(byte_data()->size());
702 : int child_data_length = children_length();
703 : Handle<PreparseData> result =
704 0 : isolate->factory()->NewPreparseData(data_size, child_data_length);
705 : result->copy_in(0, byte_data()->data(), data_size);
706 :
707 0 : for (int i = 0; i < child_data_length; i++) {
708 : ZonePreparseData* child = get_child(i);
709 : DCHECK_NOT_NULL(child);
710 0 : Handle<PreparseData> child_data = child->Serialize(isolate);
711 0 : result->set_child(i, *child_data);
712 : }
713 0 : return result;
714 : }
715 :
716 0 : ZoneConsumedPreparseData::ZoneConsumedPreparseData(Zone* zone,
717 : ZonePreparseData* data)
718 10 : : data_(data), scope_data_wrapper_(data_->byte_data()) {
719 : DCHECK(VerifyDataStart());
720 0 : }
721 :
722 228 : ZoneVectorWrapper ZoneConsumedPreparseData::GetScopeData() {
723 228 : return scope_data_wrapper_;
724 : }
725 :
726 0 : ProducedPreparseData* ZoneConsumedPreparseData::GetChildData(Zone* zone,
727 : int child_index) {
728 0 : CHECK_GT(data_->children_length(), child_index);
729 : ZonePreparseData* child_data = data_->get_child(child_index);
730 0 : if (child_data == nullptr) return nullptr;
731 0 : return ProducedPreparseData::For(child_data, zone);
732 : }
733 :
734 36738 : std::unique_ptr<ConsumedPreparseData> ConsumedPreparseData::For(
735 : Isolate* isolate, Handle<PreparseData> data) {
736 : DCHECK(!data.is_null());
737 73476 : return base::make_unique<OnHeapConsumedPreparseData>(isolate, data);
738 : }
739 :
740 10 : std::unique_ptr<ConsumedPreparseData> ConsumedPreparseData::For(
741 : Zone* zone, ZonePreparseData* data) {
742 10 : if (data == nullptr) return {};
743 20 : return base::make_unique<ZoneConsumedPreparseData>(zone, data);
744 : }
745 :
746 : } // namespace internal
747 122036 : } // namespace v8
|