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/preparsed-scope-data.h"
6 :
7 : #include "src/ast/scopes.h"
8 : #include "src/ast/variables.h"
9 : #include "src/handles.h"
10 : #include "src/objects-inl.h"
11 : #include "src/objects/shared-function-info.h"
12 : #include "src/parsing/preparser.h"
13 :
14 : namespace v8 {
15 : namespace internal {
16 :
17 : namespace {
18 :
19 : class ScopeCallsSloppyEvalField : public BitField<bool, 0, 1> {};
20 : class InnerScopeCallsEvalField
21 : : public BitField<bool, ScopeCallsSloppyEvalField::kNext, 1> {};
22 :
23 : class VariableIsUsedField : public BitField16<bool, 0, 1> {};
24 : class VariableMaybeAssignedField
25 : : public BitField16<bool, VariableIsUsedField::kNext, 1> {};
26 : class VariableContextAllocatedField
27 : : public BitField16<bool, VariableMaybeAssignedField::kNext, 1> {};
28 :
29 : const int kMagicValue = 0xc0de0de;
30 :
31 : #ifdef DEBUG
32 : const size_t kUint32Size = 5;
33 : const size_t kUint8Size = 2;
34 : #else
35 : const size_t kUint32Size = 4;
36 : const size_t kUint8Size = 1;
37 : #endif
38 :
39 : const int kPlaceholderSize = kUint32Size;
40 : const int kSkippableFunctionDataSize = 4 * kUint32Size + 1 * kUint8Size;
41 :
42 : class LanguageField : public BitField<LanguageMode, 0, 1> {};
43 : class UsesSuperField : public BitField<bool, LanguageField::kNext, 1> {};
44 : STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
45 :
46 : } // namespace
47 :
48 : /*
49 :
50 : Internal data format for the backing store of ProducedPreparsedScopeData and
51 : PreParsedScopeData::scope_data (on the heap):
52 :
53 : (Skippable function data:)
54 : ------------------------------------
55 : | scope_data_start |
56 : ------------------------------------
57 : | data for inner function 1 |
58 : | ... |
59 : ------------------------------------
60 : | data for inner function n |
61 : | ... |
62 : ------------------------------------
63 : (Scope allocation data:) << scope_data_start points here
64 : ------------------------------------
65 : magic value
66 : ------------------------------------
67 : scope positions
68 : ------------------------------------
69 : | scope type << only in debug |
70 : | eval |
71 : | ---------------------- |
72 : | | data for variables | |
73 : | | ... | |
74 : | ---------------------- |
75 : ------------------------------------
76 : ------------------------------------
77 : | data for inner scope 1 | << but not for function scopes
78 : | ... |
79 : ------------------------------------
80 : ...
81 : ------------------------------------
82 : | data for inner scope m |
83 : | ... |
84 : ------------------------------------
85 :
86 : PreParsedScopeData::child_data is an array of PreParsedScopeData objects, one
87 : for each skippable inner function.
88 :
89 : ConsumedPreParsedScopeData wraps a PreParsedScopeData and reads data from it.
90 :
91 : */
92 :
93 18 : void ProducedPreParsedScopeData::ByteData::WriteUint32(uint32_t data) {
94 : #ifdef DEBUG
95 : // Save expected item size in debug mode.
96 : backing_store_.push_back(kUint32Size);
97 : #endif
98 : const uint8_t* d = reinterpret_cast<uint8_t*>(&data);
99 12957234 : for (int i = 0; i < 4; ++i) {
100 12957216 : backing_store_.push_back(*d++);
101 : }
102 18 : }
103 :
104 97633 : void ProducedPreParsedScopeData::ByteData::OverwriteFirstUint32(uint32_t data) {
105 : size_t position = 0;
106 : #ifdef DEBUG
107 : // Check that that position already holds an item of the expected size.
108 : DCHECK_GE(backing_store_.size(), kUint32Size);
109 : DCHECK_EQ(backing_store_[0], kUint32Size);
110 : ++position;
111 : #endif
112 : const uint8_t* d = reinterpret_cast<uint8_t*>(&data);
113 488165 : for (size_t i = 0; i < 4; ++i) {
114 390532 : backing_store_[position + i] = *d++;
115 : }
116 97633 : }
117 :
118 24 : void ProducedPreParsedScopeData::ByteData::WriteUint8(uint8_t data) {
119 : #ifdef DEBUG
120 : // Save expected item size in debug mode.
121 : backing_store_.push_back(kUint8Size);
122 : #endif
123 1220697 : backing_store_.push_back(data);
124 24 : }
125 :
126 73158 : Handle<PodArray<uint8_t>> ProducedPreParsedScopeData::ByteData::Serialize(
127 : Isolate* isolate) const {
128 : Handle<PodArray<uint8_t>> array = PodArray<uint8_t>::New(
129 73158 : isolate, static_cast<int>(backing_store_.size()), TENURED);
130 :
131 : DisallowHeapAllocation no_gc;
132 : PodArray<uint8_t>* raw_array = *array;
133 :
134 : int i = 0;
135 7921202 : for (uint8_t item : backing_store_) {
136 3924022 : raw_array->set(i++, item);
137 : }
138 73158 : return array;
139 : }
140 :
141 2361661 : ProducedPreParsedScopeData::ProducedPreParsedScopeData(
142 : Zone* zone, ProducedPreParsedScopeData* parent)
143 : : parent_(parent),
144 : byte_data_(new (zone) ByteData(zone)),
145 : data_for_inner_functions_(zone),
146 7084983 : bailed_out_(false) {
147 2361661 : if (parent != nullptr) {
148 151280 : parent->data_for_inner_functions_.push_back(this);
149 : }
150 : // Reserve space for scope_data_start, written later:
151 2361661 : byte_data_->WriteUint32(0);
152 2361661 : }
153 :
154 : // Create a ProducedPreParsedScopeData which is just a proxy for a previous
155 : // produced PreParsedScopeData.
156 0 : ProducedPreParsedScopeData::ProducedPreParsedScopeData(
157 : Handle<PreParsedScopeData> data, Zone* zone)
158 : : parent_(nullptr),
159 : byte_data_(nullptr),
160 : data_for_inner_functions_(zone),
161 : bailed_out_(false),
162 3212 : previously_produced_preparsed_scope_data_(data) {}
163 :
164 2361661 : ProducedPreParsedScopeData::DataGatheringScope::DataGatheringScope(
165 2361661 : DeclarationScope* function_scope, PreParser* preparser)
166 : : function_scope_(function_scope),
167 : preparser_(preparser),
168 2361661 : produced_preparsed_scope_data_(nullptr) {
169 2361661 : if (FLAG_preparser_scope_analysis) {
170 : ProducedPreParsedScopeData* parent =
171 : preparser->produced_preparsed_scope_data();
172 : Zone* main_zone = preparser->main_zone();
173 : produced_preparsed_scope_data_ =
174 2361661 : new (main_zone) ProducedPreParsedScopeData(main_zone, parent);
175 : preparser->set_produced_preparsed_scope_data(
176 : produced_preparsed_scope_data_);
177 : function_scope->set_produced_preparsed_scope_data(
178 2361661 : produced_preparsed_scope_data_);
179 : }
180 2361661 : }
181 :
182 2361661 : ProducedPreParsedScopeData::DataGatheringScope::~DataGatheringScope() {
183 2361661 : if (FLAG_preparser_scope_analysis) {
184 : preparser_->set_produced_preparsed_scope_data(
185 2361661 : produced_preparsed_scope_data_->parent_);
186 : }
187 2361661 : }
188 :
189 146305 : void ProducedPreParsedScopeData::DataGatheringScope::MarkFunctionAsSkippable(
190 : int end_position, int num_inner_functions) {
191 : DCHECK(FLAG_preparser_scope_analysis);
192 : DCHECK_NOT_NULL(produced_preparsed_scope_data_);
193 : DCHECK_NOT_NULL(produced_preparsed_scope_data_->parent_);
194 : produced_preparsed_scope_data_->parent_->AddSkippableFunction(
195 : function_scope_->start_position(), end_position,
196 : function_scope_->num_parameters(), num_inner_functions,
197 292610 : function_scope_->language_mode(), function_scope_->NeedsHomeObject());
198 146305 : }
199 :
200 146305 : void ProducedPreParsedScopeData::AddSkippableFunction(
201 : int start_position, int end_position, int num_parameters,
202 : int num_inner_functions, LanguageMode language_mode,
203 : bool uses_super_property) {
204 : DCHECK(FLAG_preparser_scope_analysis);
205 : DCHECK(previously_produced_preparsed_scope_data_.is_null());
206 :
207 146305 : if (bailed_out_) {
208 146305 : return;
209 : }
210 :
211 146186 : byte_data_->WriteUint32(start_position);
212 146186 : byte_data_->WriteUint32(end_position);
213 146186 : byte_data_->WriteUint32(num_parameters);
214 146186 : byte_data_->WriteUint32(num_inner_functions);
215 :
216 : uint8_t language_and_super = LanguageField::encode(language_mode) |
217 292372 : UsesSuperField::encode(uses_super_property);
218 :
219 146186 : byte_data_->WriteUint8(language_and_super);
220 : }
221 :
222 1803440 : void ProducedPreParsedScopeData::SaveScopeAllocationData(
223 : DeclarationScope* scope) {
224 : DCHECK(FLAG_preparser_scope_analysis);
225 : DCHECK(previously_produced_preparsed_scope_data_.is_null());
226 : // The data contains a uint32 (reserved space for scope_data_start) and
227 : // function data items, kSkippableFunctionDataSize each.
228 : DCHECK_GE(byte_data_->size(), kPlaceholderSize);
229 : DCHECK_LE(byte_data_->size(), std::numeric_limits<uint32_t>::max());
230 : DCHECK_EQ(byte_data_->size() % kSkippableFunctionDataSize, kPlaceholderSize);
231 :
232 1803440 : if (bailed_out_) {
233 : return;
234 : }
235 :
236 3605992 : uint32_t scope_data_start = static_cast<uint32_t>(byte_data_->size());
237 :
238 : // If there are no skippable inner functions, we don't need to save anything.
239 1802996 : if (scope_data_start == kPlaceholderSize) {
240 : return;
241 : }
242 :
243 97627 : byte_data_->OverwriteFirstUint32(scope_data_start);
244 :
245 : // For a data integrity check, write a value between data about skipped inner
246 : // funcs and data about variables.
247 97627 : byte_data_->WriteUint32(kMagicValue);
248 195254 : byte_data_->WriteUint32(scope->start_position());
249 97627 : byte_data_->WriteUint32(scope->end_position());
250 :
251 97627 : SaveDataForScope(scope);
252 : }
253 :
254 540980 : bool ProducedPreParsedScopeData::ContainsInnerFunctions() const {
255 1081960 : return byte_data_->size() > kPlaceholderSize;
256 : }
257 :
258 1945395 : MaybeHandle<PreParsedScopeData> ProducedPreParsedScopeData::Serialize(
259 : Isolate* isolate) const {
260 1945395 : if (!previously_produced_preparsed_scope_data_.is_null()) {
261 : DCHECK(!bailed_out_);
262 : DCHECK_EQ(data_for_inner_functions_.size(), 0);
263 1606 : return previously_produced_preparsed_scope_data_;
264 : }
265 1943789 : if (bailed_out_) {
266 453 : return MaybeHandle<PreParsedScopeData>();
267 : }
268 :
269 : DCHECK(!ThisOrParentBailedOut());
270 :
271 3886672 : if (byte_data_->size() <= kPlaceholderSize) {
272 : // The data contains only the placeholder.
273 1870184 : return MaybeHandle<PreParsedScopeData>();
274 : }
275 :
276 73152 : Handle<PreParsedScopeData> data = isolate->factory()->NewPreParsedScopeData();
277 :
278 73152 : Handle<PodArray<uint8_t>> scope_data_array = byte_data_->Serialize(isolate);
279 73152 : data->set_scope_data(*scope_data_array);
280 :
281 73152 : int child_data_length = static_cast<int>(data_for_inner_functions_.size());
282 73152 : if (child_data_length == 0) {
283 0 : data->set_child_data(*(isolate->factory()->empty_fixed_array()));
284 : } else {
285 : Handle<FixedArray> child_array =
286 73152 : isolate->factory()->NewFixedArray(child_data_length, TENURED);
287 : int i = 0;
288 183716 : for (const auto& item : data_for_inner_functions_) {
289 : MaybeHandle<PreParsedScopeData> maybe_child_data =
290 110564 : item->Serialize(isolate);
291 110564 : if (maybe_child_data.is_null()) {
292 210392 : child_array->set(i++, *(isolate->factory()->null_value()));
293 : } else {
294 : Handle<PreParsedScopeData> child_data =
295 : maybe_child_data.ToHandleChecked();
296 10736 : child_array->set(i++, *child_data);
297 : }
298 : }
299 73152 : data->set_child_data(*child_array);
300 : }
301 :
302 73152 : return data;
303 : }
304 :
305 519587 : bool ProducedPreParsedScopeData::ScopeNeedsData(Scope* scope) {
306 449363 : if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
307 : // Default constructors don't need data (they cannot contain inner functions
308 : // defined by the user). Other functions do.
309 603390 : return !IsDefaultConstructor(scope->AsDeclarationScope()->function_kind());
310 : }
311 147668 : if (!scope->is_hidden()) {
312 285476 : for (Variable* var : *scope->locals()) {
313 77444 : if (IsDeclaredVariableMode(var->mode())) {
314 : return true;
315 : }
316 : }
317 : }
318 89818 : for (Scope* inner = scope->inner_scope(); inner != nullptr;
319 : inner = inner->sibling()) {
320 33173 : if (ScopeNeedsData(inner)) {
321 : return true;
322 : }
323 : }
324 : return false;
325 : }
326 :
327 2888617 : bool ProducedPreParsedScopeData::ScopeIsSkippableFunctionScope(Scope* scope) {
328 : // Lazy non-arrow function scopes are skippable. Lazy functions are exactly
329 : // those Scopes which have their own ProducedPreParsedScopeData object. This
330 : // logic ensures that the scope allocation data is consistent with the
331 : // skippable function data (both agree on where the lazy function boundaries
332 : // are).
333 2888617 : if (scope->scope_type() != ScopeType::FUNCTION_SCOPE) {
334 : return false;
335 : }
336 4323400 : DeclarationScope* declaration_scope = scope->AsDeclarationScope();
337 4323400 : return !declaration_scope->is_arrow_scope() &&
338 2327492 : declaration_scope->produced_preparsed_scope_data() != nullptr;
339 : }
340 :
341 447936 : void ProducedPreParsedScopeData::SaveDataForScope(Scope* scope) {
342 : DCHECK_NE(scope->end_position(), kNoSourcePosition);
343 :
344 230570 : if (!ScopeNeedsData(scope)) {
345 230570 : return;
346 : }
347 :
348 : #ifdef DEBUG
349 : byte_data_->WriteUint8(scope->scope_type());
350 : #endif
351 :
352 : uint8_t eval =
353 : ScopeCallsSloppyEvalField::encode(
354 388410 : scope->is_declaration_scope() &&
355 171044 : scope->AsDeclarationScope()->calls_sloppy_eval()) |
356 434732 : InnerScopeCallsEvalField::encode(scope->inner_scope_calls_eval());
357 217366 : byte_data_->WriteUint8(eval);
358 :
359 217366 : if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
360 169642 : Variable* function = scope->AsDeclarationScope()->function_var();
361 169642 : if (function != nullptr) {
362 4754 : SaveDataForVariable(function);
363 : }
364 : }
365 :
366 2139466 : for (Variable* var : *scope->locals()) {
367 852367 : if (IsDeclaredVariableMode(var->mode())) {
368 852367 : SaveDataForVariable(var);
369 : }
370 : }
371 :
372 217366 : SaveDataForInnerScopes(scope);
373 : }
374 :
375 857121 : void ProducedPreParsedScopeData::SaveDataForVariable(Variable* var) {
376 : #ifdef DEBUG
377 : // Store the variable name in debug mode; this way we can check that we
378 : // restore data to the correct variable.
379 : const AstRawString* name = var->raw_name();
380 : byte_data_->WriteUint32(name->length());
381 : for (int i = 0; i < name->length(); ++i) {
382 : byte_data_->WriteUint8(name->raw_data()[i]);
383 : }
384 : #endif
385 : // FIXME(marja): Only 3 bits needed, not a full byte.
386 : byte variable_data = VariableIsUsedField::encode(var->is_used()) |
387 : VariableMaybeAssignedField::encode(
388 857121 : var->maybe_assigned() == kMaybeAssigned) |
389 : VariableContextAllocatedField::encode(
390 2571363 : var->has_forced_context_allocation());
391 :
392 857121 : byte_data_->WriteUint8(variable_data);
393 857121 : }
394 :
395 434732 : void ProducedPreParsedScopeData::SaveDataForInnerScopes(Scope* scope) {
396 : // Inner scopes are stored in the reverse order, but we'd like to write the
397 : // data in the logical order. There might be many inner scopes, so we don't
398 : // want to recurse here.
399 : std::vector<Scope*> scopes;
400 495298 : for (Scope* inner = scope->inner_scope(); inner != nullptr;
401 277932 : inner = inner->sibling()) {
402 555864 : if (ScopeIsSkippableFunctionScope(inner)) {
403 : // Don't save data about function scopes, since they'll have their own
404 : // ProducedPreParsedScopeData where their data is saved.
405 : DCHECK_NOT_NULL(
406 : inner->AsDeclarationScope()->produced_preparsed_scope_data());
407 : continue;
408 : }
409 132943 : scopes.push_back(inner);
410 : }
411 350309 : for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
412 132943 : SaveDataForScope(*it);
413 : }
414 217366 : }
415 :
416 0 : ConsumedPreParsedScopeData::ByteData::ReadingScope::ReadingScope(
417 : ConsumedPreParsedScopeData* parent)
418 0 : : ReadingScope(parent->scope_data_.get(), parent->data_->scope_data()) {}
419 :
420 18 : int32_t ConsumedPreParsedScopeData::ByteData::ReadUint32() {
421 : DCHECK_NOT_NULL(data_);
422 : DCHECK_GE(RemainingBytes(), kUint32Size);
423 : #ifdef DEBUG
424 : // Check that there indeed is an integer following.
425 : DCHECK_EQ(data_->get(index_++), kUint32Size);
426 : #endif
427 264548 : int32_t result = 0;
428 : byte* p = reinterpret_cast<byte*>(&result);
429 1058210 : for (int i = 0; i < 4; ++i) {
430 2116384 : *p++ = data_->get(index_++);
431 : }
432 264548 : return result;
433 : }
434 :
435 24 : uint8_t ConsumedPreParsedScopeData::ByteData::ReadUint8() {
436 : DCHECK_NOT_NULL(data_);
437 : DCHECK_GE(RemainingBytes(), kUint8Size);
438 : #ifdef DEBUG
439 : // Check that there indeed is a byte following.
440 : DCHECK_EQ(data_->get(index_++), kUint8Size);
441 : #endif
442 407965 : return data_->get(index_++);
443 : }
444 :
445 2806595 : ConsumedPreParsedScopeData::ConsumedPreParsedScopeData()
446 5613190 : : scope_data_(new ByteData()), child_index_(0) {}
447 :
448 5613179 : ConsumedPreParsedScopeData::~ConsumedPreParsedScopeData() {}
449 :
450 35582 : void ConsumedPreParsedScopeData::SetData(Handle<PreParsedScopeData> data) {
451 : DCHECK(data->IsPreParsedScopeData());
452 35582 : data_ = data;
453 : #ifdef DEBUG
454 : ByteData::ReadingScope reading_scope(this);
455 : int scope_data_start = scope_data_->ReadUint32();
456 : scope_data_->SetPosition(scope_data_start);
457 : DCHECK_EQ(scope_data_->ReadUint32(), kMagicValue);
458 : #endif
459 : // The first data item is scope_data_start. Skip over it.
460 : scope_data_->SetPosition(kPlaceholderSize);
461 35582 : }
462 :
463 : ProducedPreParsedScopeData*
464 35336 : ConsumedPreParsedScopeData::GetDataForSkippableFunction(
465 : Zone* zone, int start_position, int* end_position, int* num_parameters,
466 : int* num_inner_functions, bool* uses_super_property,
467 : LanguageMode* language_mode) {
468 : // The skippable function *must* be the next function in the data. Use the
469 : // start position as a sanity check.
470 : ByteData::ReadingScope reading_scope(this);
471 70672 : CHECK_GE(scope_data_->RemainingBytes(), kSkippableFunctionDataSize);
472 : int start_position_from_data = scope_data_->ReadUint32();
473 35336 : CHECK_EQ(start_position, start_position_from_data);
474 :
475 35336 : *end_position = scope_data_->ReadUint32();
476 : DCHECK_GT(*end_position, start_position);
477 35336 : *num_parameters = scope_data_->ReadUint32();
478 35336 : *num_inner_functions = scope_data_->ReadUint32();
479 :
480 : uint8_t language_and_super = scope_data_->ReadUint8();
481 35336 : *language_mode = LanguageMode(LanguageField::decode(language_and_super));
482 35336 : *uses_super_property = UsesSuperField::decode(language_and_super);
483 :
484 : // Retrieve the corresponding PreParsedScopeData and associate it to the
485 : // skipped function. If the skipped functions contains inner functions, those
486 : // can be skipped when the skipped function is eagerly parsed.
487 : FixedArray* children = data_->child_data();
488 70672 : CHECK_GT(children->length(), child_index_);
489 35336 : Object* child_data = children->get(child_index_++);
490 35336 : if (!child_data->IsPreParsedScopeData()) {
491 : return nullptr;
492 : }
493 : Handle<PreParsedScopeData> child_data_handle(
494 : PreParsedScopeData::cast(child_data));
495 : return new (zone) ProducedPreParsedScopeData(child_data_handle, zone);
496 : }
497 :
498 35582 : void ConsumedPreParsedScopeData::RestoreScopeAllocationData(
499 : DeclarationScope* scope) {
500 : DCHECK(FLAG_preparser_scope_analysis);
501 : DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
502 : DCHECK(!data_.is_null());
503 :
504 : ByteData::ReadingScope reading_scope(this);
505 :
506 : int magic_value_from_data = scope_data_->ReadUint32();
507 : // Check that we've consumed all inner function data.
508 35582 : CHECK_EQ(magic_value_from_data, kMagicValue);
509 :
510 : int start_position_from_data = scope_data_->ReadUint32();
511 : int end_position_from_data = scope_data_->ReadUint32();
512 35582 : CHECK_EQ(start_position_from_data, scope->start_position());
513 35582 : CHECK_EQ(end_position_from_data, scope->end_position());
514 :
515 35582 : RestoreData(scope);
516 :
517 : // Check that we consumed all scope data.
518 : DCHECK_EQ(scope_data_->RemainingBytes(), 0);
519 35582 : }
520 :
521 16440 : void ConsumedPreParsedScopeData::SkipFunctionDataForTesting() {
522 : ByteData::ReadingScope reading_scope(this);
523 : scope_data_->SetPosition(0);
524 : uint32_t scope_data_start = scope_data_->ReadUint32();
525 : scope_data_->SetPosition(scope_data_start);
526 16440 : }
527 :
528 268839 : void ConsumedPreParsedScopeData::RestoreData(Scope* scope) {
529 315295 : if (scope->is_declaration_scope() &&
530 142669 : scope->AsDeclarationScope()->is_skipped_function()) {
531 : return;
532 : }
533 :
534 : // It's possible that scope is not present in the data at all (since PreParser
535 : // doesn't create the corresponding scope). In this case, the Scope won't
536 : // contain any variables for which we need the data.
537 110572 : if (!ProducedPreParsedScopeData::ScopeNeedsData(scope)) {
538 : return;
539 : }
540 :
541 192426 : if (scope_data_->RemainingBytes() < kUint8Size) {
542 : // Temporary debugging code for detecting inconsistent data. Write debug
543 : // information on the stack, then crash.
544 : data_->GetIsolate()->PushStackTraceAndDie(0xc0defee, nullptr, nullptr,
545 0 : 0xc0defee);
546 : }
547 :
548 : // scope_type is stored only in debug mode.
549 192426 : CHECK_GE(scope_data_->RemainingBytes(), kUint8Size);
550 : DCHECK_EQ(scope_data_->ReadUint8(), scope->scope_type());
551 :
552 : uint32_t eval = scope_data_->ReadUint8();
553 96213 : if (ScopeCallsSloppyEvalField::decode(eval)) {
554 : scope->RecordEvalCall();
555 : }
556 96213 : if (InnerScopeCallsEvalField::decode(eval)) {
557 : scope->RecordInnerScopeEvalCall();
558 : }
559 :
560 96213 : if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
561 78855 : Variable* function = scope->AsDeclarationScope()->function_var();
562 78855 : if (function != nullptr) {
563 2613 : RestoreDataForVariable(function);
564 : }
565 : }
566 :
567 856088 : for (Variable* var : *scope->locals()) {
568 331831 : if (IsDeclaredVariableMode(var->mode())) {
569 273755 : RestoreDataForVariable(var);
570 : }
571 : }
572 :
573 96213 : RestoreDataForInnerScopes(scope);
574 : }
575 :
576 276368 : void ConsumedPreParsedScopeData::RestoreDataForVariable(Variable* var) {
577 : #ifdef DEBUG
578 : const AstRawString* name = var->raw_name();
579 : DCHECK_EQ(scope_data_->ReadUint32(), static_cast<uint32_t>(name->length()));
580 : for (int i = 0; i < name->length(); ++i) {
581 : DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[i]);
582 : }
583 : #endif
584 552736 : CHECK_GE(scope_data_->RemainingBytes(), kUint8Size);
585 : uint8_t variable_data = scope_data_->ReadUint8();
586 276368 : if (VariableIsUsedField::decode(variable_data)) {
587 : var->set_is_used();
588 : }
589 276368 : if (VariableMaybeAssignedField::decode(variable_data)) {
590 : var->set_maybe_assigned();
591 : }
592 276368 : if (VariableContextAllocatedField::decode(variable_data)) {
593 : var->ForceContextAllocation();
594 : }
595 276368 : }
596 :
597 192426 : void ConsumedPreParsedScopeData::RestoreDataForInnerScopes(Scope* scope) {
598 : std::vector<Scope*> scopes;
599 233257 : for (Scope* inner = scope->inner_scope(); inner != nullptr;
600 137044 : inner = inner->sibling()) {
601 137044 : scopes.push_back(inner);
602 : }
603 233257 : for (auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
604 137044 : RestoreData(*it);
605 : }
606 96213 : }
607 :
608 : } // namespace internal
609 : } // namespace v8
|