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