5 #include "src/parsing/preparsed-scope-data.h" 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/preparsed-scope-data-impl.h" 15 #include "src/parsing/preparser.h" 22 class ScopeCallsSloppyEvalField :
public BitField<bool, 0, 1> {};
23 class InnerScopeCallsEvalField
24 :
public BitField<bool, ScopeCallsSloppyEvalField::kNext, 1> {};
26 class VariableMaybeAssignedField :
public BitField8<bool, 0, 1> {};
27 class VariableContextAllocatedField
28 :
public BitField8<bool, VariableMaybeAssignedField::kNext, 1> {};
30 class LanguageField :
public BitField8<LanguageMode, 0, 1> {};
31 class UsesSuperField :
public BitField8<bool, LanguageField::kNext, 1> {};
32 STATIC_ASSERT(LanguageModeSize <= LanguageField::kNumValues);
81 void PreParsedScopeDataBuilder::ByteData::WriteUint32(
uint32_t data) {
84 backing_store_.push_back(kUint32Size);
86 const uint8_t* d =
reinterpret_cast<uint8_t*
>(&data);
87 for (
int i = 0;
i < 4; ++
i) {
88 backing_store_.push_back(*d++);
90 free_quarters_in_last_byte_ = 0;
94 void PreParsedScopeDataBuilder::ByteData::OverwriteFirstUint32(
uint32_t data) {
95 auto it = backing_store_.begin();
97 DCHECK_GE(backing_store_.size(), kUint32Size);
98 DCHECK_EQ(*it, kUint32Size);
100 const uint8_t* d =
reinterpret_cast<uint8_t*
>(&data);
101 for (
size_t i = 0;
i < 4; ++
i) {
107 void PreParsedScopeDataBuilder::ByteData::WriteUint8(uint8_t data) {
110 backing_store_.push_back(kUint8Size);
112 backing_store_.push_back(data);
113 free_quarters_in_last_byte_ = 0;
116 void PreParsedScopeDataBuilder::ByteData::WriteQuarter(uint8_t data) {
118 if (free_quarters_in_last_byte_ == 0) {
121 backing_store_.push_back(kQuarterMarker);
123 backing_store_.push_back(0);
124 free_quarters_in_last_byte_ = 3;
126 --free_quarters_in_last_byte_;
129 uint8_t shift_amount = free_quarters_in_last_byte_ * 2;
130 DCHECK_EQ(backing_store_.back() & (3 << shift_amount), 0);
131 backing_store_.back() |= (data << shift_amount);
134 Handle<PodArray<uint8_t>> PreParsedScopeDataBuilder::ByteData::Serialize(
136 Handle<PodArray<uint8_t>> array = PodArray<uint8_t>::New(
137 isolate, static_cast<int>(backing_store_.size()), TENURED);
139 DisallowHeapAllocation no_gc;
140 PodArray<uint8_t> raw_array = *array;
143 for (uint8_t item : backing_store_) {
144 raw_array->set(
i++, item);
149 PreParsedScopeDataBuilder::PreParsedScopeDataBuilder(
150 Zone* zone, PreParsedScopeDataBuilder* parent)
152 byte_data_(new (zone) ByteData(zone)),
153 data_for_inner_functions_(zone),
155 if (parent !=
nullptr) {
156 parent->data_for_inner_functions_.push_back(
this);
160 byte_data_->WriteUint32(0);
164 PreParsedScopeDataBuilder::DataGatheringScope::DataGatheringScope(
165 DeclarationScope* function_scope, PreParser* preparser)
166 : preparser_(preparser), builder_(nullptr) {
167 PreParsedScopeDataBuilder* parent = preparser->preparsed_scope_data_builder();
168 Zone* main_zone = preparser->main_zone();
169 builder_ =
new (main_zone) PreParsedScopeDataBuilder(main_zone, parent);
170 preparser->set_preparsed_scope_data_builder(builder_);
171 function_scope->set_preparsed_scope_data_builder(builder_);
174 PreParsedScopeDataBuilder::DataGatheringScope::~DataGatheringScope() {
175 preparser_->set_preparsed_scope_data_builder(builder_->parent_);
178 void PreParsedScopeDataBuilder::AddSkippableFunction(
int start_position,
181 int num_inner_functions,
182 LanguageMode language_mode,
183 bool uses_super_property) {
191 byte_data_->WriteUint32(start_position);
192 byte_data_->WriteUint32(end_position);
193 byte_data_->WriteUint32(num_parameters);
194 byte_data_->WriteUint32(num_inner_functions);
196 uint8_t language_and_super = LanguageField::encode(language_mode) |
197 UsesSuperField::encode(uses_super_property);
199 byte_data_->WriteQuarter(language_and_super);
202 void PreParsedScopeDataBuilder::SaveScopeAllocationData(
203 DeclarationScope* scope) {
206 DCHECK_GE(byte_data_->size(), ByteData::kPlaceholderSize);
207 DCHECK_LE(byte_data_->size(), std::numeric_limits<uint32_t>::max());
208 DCHECK_EQ(byte_data_->size() % ByteData::kSkippableFunctionDataSize,
209 ByteData::kPlaceholderSize);
218 if (scope_data_start == ByteData::kPlaceholderSize) {
223 byte_data_->OverwriteFirstUint32(scope_data_start);
227 byte_data_->WriteUint32(ByteData::kMagicValue);
228 byte_data_->WriteUint32(scope->start_position());
229 byte_data_->WriteUint32(scope->end_position());
232 SaveDataForScope(scope);
235 bool PreParsedScopeDataBuilder::ContainsInnerFunctions()
const {
236 return byte_data_->size() > ByteData::kPlaceholderSize;
239 MaybeHandle<PreParsedScopeData> PreParsedScopeDataBuilder::Serialize(
242 return MaybeHandle<PreParsedScopeData>();
245 DCHECK(!ThisOrParentBailedOut());
247 if (byte_data_->size() <= ByteData::kPlaceholderSize) {
249 return MaybeHandle<PreParsedScopeData>();
252 int child_data_length =
static_cast<int>(data_for_inner_functions_.size());
253 Handle<PreParsedScopeData> data =
254 isolate->factory()->NewPreParsedScopeData(child_data_length);
256 Handle<PodArray<uint8_t>> scope_data_array = byte_data_->Serialize(isolate);
257 data->set_scope_data(*scope_data_array);
260 for (
const auto& item : data_for_inner_functions_) {
261 Handle<PreParsedScopeData> child_data;
262 if (item->Serialize(isolate).ToHandle(&child_data)) {
263 data->set_child_data(
i, *child_data);
265 DCHECK(data->child_data(
i)->IsNull());
273 ZonePreParsedScopeData* PreParsedScopeDataBuilder::Serialize(Zone* zone) {
278 DCHECK(!ThisOrParentBailedOut());
280 if (byte_data_->size() <= ByteData::kPlaceholderSize) {
285 int child_length =
static_cast<int>(data_for_inner_functions_.size());
286 ZonePreParsedScopeData* result =
new (zone) ZonePreParsedScopeData(
287 zone, byte_data_->begin(), byte_data_->end(), child_length);
290 for (
const auto& item : data_for_inner_functions_) {
291 ZonePreParsedScopeData* child = item->Serialize(zone);
292 result->set_child(
i, child);
299 bool PreParsedScopeDataBuilder::ScopeNeedsData(Scope* scope) {
300 if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
303 return !IsDefaultConstructor(scope->AsDeclarationScope()->function_kind());
305 if (!scope->is_hidden()) {
306 for (Variable* var : *scope->locals()) {
307 if (IsDeclaredVariableMode(var->mode())) {
312 for (Scope* inner = scope->inner_scope(); inner !=
nullptr;
313 inner = inner->sibling()) {
314 if (ScopeNeedsData(inner)) {
321 bool PreParsedScopeDataBuilder::ScopeIsSkippableFunctionScope(Scope* scope) {
327 if (scope->scope_type() != ScopeType::FUNCTION_SCOPE) {
330 DeclarationScope* declaration_scope = scope->AsDeclarationScope();
331 return !declaration_scope->is_arrow_scope() &&
332 declaration_scope->preparsed_scope_data_builder() !=
nullptr;
335 void PreParsedScopeDataBuilder::SaveDataForScope(Scope* scope) {
336 DCHECK_NE(scope->end_position(), kNoSourcePosition);
338 if (!ScopeNeedsData(scope)) {
343 byte_data_->WriteUint8(scope->scope_type());
347 ScopeCallsSloppyEvalField::encode(
348 scope->is_declaration_scope() &&
349 scope->AsDeclarationScope()->calls_sloppy_eval()) |
350 InnerScopeCallsEvalField::encode(scope->inner_scope_calls_eval());
351 byte_data_->WriteUint8(eval);
353 if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
354 Variable*
function = scope->AsDeclarationScope()->function_var();
355 if (
function !=
nullptr) {
356 SaveDataForVariable(
function);
360 for (Variable* var : *scope->locals()) {
361 if (IsDeclaredVariableMode(var->mode())) {
362 SaveDataForVariable(var);
366 SaveDataForInnerScopes(scope);
369 void PreParsedScopeDataBuilder::SaveDataForVariable(Variable* var) {
373 const AstRawString* name = var->raw_name();
374 byte_data_->WriteUint8(name->is_one_byte());
375 byte_data_->WriteUint32(name->length());
376 for (
int i = 0;
i < name->length(); ++
i) {
377 byte_data_->WriteUint8(name->raw_data()[
i]);
380 byte variable_data = VariableMaybeAssignedField::encode(
381 var->maybe_assigned() == kMaybeAssigned) |
382 VariableContextAllocatedField::encode(
383 var->has_forced_context_allocation());
384 byte_data_->WriteQuarter(variable_data);
387 void PreParsedScopeDataBuilder::SaveDataForInnerScopes(Scope* scope) {
391 std::vector<Scope*> scopes;
392 for (Scope* inner = scope->inner_scope(); inner !=
nullptr;
393 inner = inner->sibling()) {
394 if (ScopeIsSkippableFunctionScope(inner)) {
398 inner->AsDeclarationScope()->preparsed_scope_data_builder());
401 scopes.push_back(inner);
403 for (
auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
404 SaveDataForScope(*it);
412 : builder_(builder) {}
415 return builder_->Serialize(isolate);
419 return builder_->Serialize(zone);
451 return data_->Serialize(isolate);
465 ProducedPreParsedScopeData* ProducedPreParsedScopeData::For(
467 return new (zone) OnHeapProducedPreParsedScopeData(data);
470 ProducedPreParsedScopeData* ProducedPreParsedScopeData::For(
471 ZonePreParsedScopeData* data, Zone* zone) {
472 return new (zone) ZoneProducedPreParsedScopeData(data);
475 template <
class Data>
476 ProducedPreParsedScopeData*
477 BaseConsumedPreParsedScopeData<Data>::GetDataForSkippableFunction(
478 Zone* zone,
int start_position,
int* end_position,
int* num_parameters,
479 int* num_inner_functions,
bool* uses_super_property,
480 LanguageMode* language_mode) {
483 typename ByteData::ReadingScope reading_scope(
this);
484 CHECK_GE(scope_data_->RemainingBytes(), ByteData::kSkippableFunctionDataSize);
485 int start_position_from_data = scope_data_->ReadUint32();
486 CHECK_EQ(start_position, start_position_from_data);
488 *end_position = scope_data_->ReadUint32();
489 DCHECK_GT(*end_position, start_position);
490 *num_parameters = scope_data_->ReadUint32();
491 *num_inner_functions = scope_data_->ReadUint32();
493 uint8_t language_and_super = scope_data_->ReadQuarter();
494 *language_mode = LanguageMode(LanguageField::decode(language_and_super));
495 *uses_super_property = UsesSuperField::decode(language_and_super);
500 return GetChildData(zone, child_index_++);
503 template <
class Data>
504 void BaseConsumedPreParsedScopeData<Data>::RestoreScopeAllocationData(
505 DeclarationScope* scope) {
506 DCHECK_EQ(scope->scope_type(), ScopeType::FUNCTION_SCOPE);
507 typename ByteData::ReadingScope reading_scope(
this);
510 int magic_value_from_data = scope_data_->ReadUint32();
512 DCHECK_EQ(magic_value_from_data, ByteData::kMagicValue);
514 int start_position_from_data = scope_data_->ReadUint32();
515 int end_position_from_data = scope_data_->ReadUint32();
516 DCHECK_EQ(start_position_from_data, scope->start_position());
517 DCHECK_EQ(end_position_from_data, scope->end_position());
523 DCHECK_EQ(scope_data_->RemainingBytes(), 0);
526 template <
typename Data>
527 void BaseConsumedPreParsedScopeData<Data>::RestoreData(Scope* scope) {
528 if (scope->is_declaration_scope() &&
529 scope->AsDeclarationScope()->is_skipped_function()) {
536 if (!PreParsedScopeDataBuilder::ScopeNeedsData(scope)) {
541 CHECK_GE(scope_data_->RemainingBytes(), ByteData::kUint8Size);
542 DCHECK_EQ(scope_data_->ReadUint8(), scope->scope_type());
544 uint32_t eval = scope_data_->ReadUint8();
545 if (ScopeCallsSloppyEvalField::decode(eval)) {
546 scope->RecordEvalCall();
548 if (InnerScopeCallsEvalField::decode(eval)) {
549 scope->RecordInnerScopeEvalCall();
552 if (scope->scope_type() == ScopeType::FUNCTION_SCOPE) {
553 Variable*
function = scope->AsDeclarationScope()->function_var();
554 if (
function !=
nullptr) {
555 RestoreDataForVariable(
function);
559 for (Variable* var : *scope->locals()) {
560 if (IsDeclaredVariableMode(var->mode())) {
561 RestoreDataForVariable(var);
565 RestoreDataForInnerScopes(scope);
568 template <
typename Data>
569 void BaseConsumedPreParsedScopeData<Data>::RestoreDataForVariable(
572 const AstRawString* name = var->raw_name();
573 bool data_one_byte = scope_data_->ReadUint8();
574 DCHECK_IMPLIES(name->is_one_byte(), data_one_byte);
575 DCHECK_EQ(scope_data_->ReadUint32(),
static_cast<uint32_t>(name->length()));
576 if (!name->is_one_byte() && data_one_byte) {
579 for (
int i = 0;
i < 2 * name->length();
i += 2) {
580 #if defined(V8_TARGET_LITTLE_ENDIAN) 581 DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[
i]);
582 DCHECK_EQ(0, name->raw_data()[
i + 1]);
584 DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[
i + 1]);
585 DCHECK_EQ(0, name->raw_data()[
i]);
586 #endif // V8_TARGET_LITTLE_ENDIAN 589 for (
int i = 0;
i < name->length(); ++
i) {
590 DCHECK_EQ(scope_data_->ReadUint8(), name->raw_data()[
i]);
594 uint8_t variable_data = scope_data_->ReadQuarter();
595 if (VariableMaybeAssignedField::decode(variable_data)) {
596 var->set_maybe_assigned();
598 if (VariableContextAllocatedField::decode(variable_data)) {
600 var->ForceContextAllocation();
604 template <
typename Data>
605 void BaseConsumedPreParsedScopeData<Data>::RestoreDataForInnerScopes(
607 std::vector<Scope*> scopes;
608 for (Scope* inner = scope->inner_scope(); inner !=
nullptr;
609 inner = inner->sibling()) {
610 scopes.push_back(inner);
612 for (
auto it = scopes.rbegin(); it != scopes.rend(); ++it) {
618 template <
class Data>
619 void BaseConsumedPreParsedScopeData<Data>::VerifyDataStart() {
620 typename ByteData::ReadingScope reading_scope(
this);
621 int scope_data_start = scope_data_->ReadUint32();
622 scope_data_->SetPosition(scope_data_start);
623 DCHECK_EQ(scope_data_->ReadUint32(), ByteData::kMagicValue);
625 scope_data_->SetPosition(ByteData::kPlaceholderSize);
629 PodArray<uint8_t> OnHeapConsumedPreParsedScopeData::GetScopeData() {
630 return data_->scope_data();
633 ProducedPreParsedScopeData* OnHeapConsumedPreParsedScopeData::GetChildData(
634 Zone* zone,
int child_index) {
635 CHECK_GT(data_->length(), child_index);
636 Object* child_data = data_->child_data(child_index);
637 if (!child_data->IsPreParsedScopeData()) {
640 Handle<PreParsedScopeData> child_data_handle(
641 PreParsedScopeData::cast(child_data), isolate_);
642 return ProducedPreParsedScopeData::For(child_data_handle, zone);
645 OnHeapConsumedPreParsedScopeData::OnHeapConsumedPreParsedScopeData(
646 Isolate* isolate, Handle<PreParsedScopeData> data)
647 : BaseConsumedPreParsedScopeData<PodArray<uint8_t>>(),
650 DCHECK_NOT_NULL(isolate);
651 DCHECK(data->IsPreParsedScopeData());
657 ZonePreParsedScopeData::ZonePreParsedScopeData(
658 Zone* zone, ZoneChunkList<uint8_t>::iterator byte_data_begin,
659 ZoneChunkList<uint8_t>::iterator byte_data_end,
int child_length)
660 : byte_data_(byte_data_begin, byte_data_end, zone),
661 children_(child_length, zone) {}
663 Handle<PreParsedScopeData> ZonePreParsedScopeData::Serialize(Isolate* isolate) {
664 int child_data_length = child_length();
665 Handle<PreParsedScopeData> result =
666 isolate->factory()->NewPreParsedScopeData(child_data_length);
668 Handle<PodArray<uint8_t>> scope_data_array = PodArray<uint8_t>::New(
669 isolate, static_cast<int>(byte_data()->size()), TENURED);
670 scope_data_array->copy_in(0, byte_data()->data(),
671 static_cast<int>(byte_data()->size()));
672 result->set_scope_data(*scope_data_array);
674 for (
int i = 0;
i < child_data_length;
i++) {
675 ZonePreParsedScopeData* child = get_child(
i);
677 Handle<PreParsedScopeData> child_data = child->Serialize(isolate);
678 result->set_child_data(
i, *child_data);
684 ZoneConsumedPreParsedScopeData::ZoneConsumedPreParsedScopeData(
685 Zone* zone, ZonePreParsedScopeData* data)
686 : data_(data), scope_data_wrapper_(data_->byte_data()) {
692 ZoneVectorWrapper ZoneConsumedPreParsedScopeData::GetScopeData() {
693 return scope_data_wrapper_;
696 ProducedPreParsedScopeData* ZoneConsumedPreParsedScopeData::GetChildData(
697 Zone* zone,
int child_index) {
698 CHECK_GT(data_->child_length(), child_index);
699 ZonePreParsedScopeData* child_data = data_->get_child(child_index);
700 if (child_data ==
nullptr) {
703 return ProducedPreParsedScopeData::For(child_data, zone);
706 std::unique_ptr<ConsumedPreParsedScopeData> ConsumedPreParsedScopeData::For(
707 Isolate* isolate, Handle<PreParsedScopeData> data) {
708 DCHECK(!data.is_null());
709 return base::make_unique<OnHeapConsumedPreParsedScopeData>(isolate, data);
712 std::unique_ptr<ConsumedPreParsedScopeData> ConsumedPreParsedScopeData::For(
713 Zone* zone, ZonePreParsedScopeData* data) {
714 if (data ==
nullptr)
return {};
715 return base::make_unique<ZoneConsumedPreParsedScopeData>(zone, data);