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