Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(729)

Side by Side Diff: vm/object.cc

Issue 10697055: Represent tokens as a compressed stream instead of an array. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "platform/assert.h" 7 #include "platform/assert.h"
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/bigint_operations.h" 9 #include "vm/bigint_operations.h"
10 #include "vm/bootstrap.h" 10 #include "vm/bootstrap.h"
(...skipping 4337 matching lines...) Expand 10 before | Expand all | Expand 10 after
4348 return result.raw(); 4348 return result.raw();
4349 } 4349 }
4350 4350
4351 4351
4352 const char* LiteralToken::ToCString() const { 4352 const char* LiteralToken::ToCString() const {
4353 const String& token = String::Handle(literal()); 4353 const String& token = String::Handle(literal());
4354 return token.ToCString(); 4354 return token.ToCString();
4355 } 4355 }
4356 4356
4357 4357
4358 RawArray* TokenStream::TokenObjects() const {
4359 return raw_ptr()->token_objects_;
4360 }
4361
4362
4363 void TokenStream::SetTokenObjects(const Array& value) const {
4364 StorePointer(&raw_ptr()->token_objects_, value.raw());
4365 }
4366
4367
4358 void TokenStream::SetLength(intptr_t value) const { 4368 void TokenStream::SetLength(intptr_t value) const {
4359 raw_ptr()->length_ = Smi::New(value); 4369 raw_ptr()->length_ = value;
4360 }
4361
4362
4363 void TokenStream::SetTokenAt(intptr_t index,
4364 Token::Kind kind,
4365 const String& literal) {
4366 if (kind == Token::kIDENT) {
4367 if (FLAG_compiler_stats) {
4368 CompilerStats::num_ident_tokens_total += 1;
4369 }
4370 StorePointer(EntryAddr(index), reinterpret_cast<RawObject*>(literal.raw()));
4371 } else if (Token::NeedsLiteralToken(kind)) {
4372 if (FLAG_compiler_stats) {
4373 CompilerStats::num_literal_tokens_total += 1;
4374 }
4375 StorePointer(
4376 EntryAddr(index),
4377 reinterpret_cast<RawObject*>(LiteralToken::New(kind, literal)));
4378 } else {
4379 ASSERT(kind < Token::kNumTokens);
4380 *(SmiAddr(index)) = Smi::New(kind);
4381 }
4382 }
4383
4384
4385 void TokenStream::SetTokenAt(intptr_t index, const Object& token) {
4386 StorePointer(EntryAddr(index), token.raw());
4387 }
4388
4389
4390 RawObject* TokenStream::TokenAt(intptr_t index) const {
4391 return *EntryAddr(index);
4392 }
4393
4394
4395 RawString* TokenStream::LiteralAt(intptr_t index) const {
4396 const Object& obj = Object::Handle(TokenAt(index));
4397 if (obj.IsString()) {
4398 return reinterpret_cast<RawString*>(obj.raw());
4399 } else if (obj.IsSmi()) {
4400 Token::Kind kind = static_cast<Token::Kind>(
4401 Smi::Value(reinterpret_cast<RawSmi*>(obj.raw())));
4402 ASSERT(kind < Token::kNumTokens);
4403 if (Token::IsPseudoKeyword(kind) || Token::IsKeyword(kind)) {
4404 Isolate* isolate = Isolate::Current();
4405 ObjectStore* object_store = isolate->object_store();
4406 String& str = String::Handle(isolate, String::null());
4407 const Array& symbols = Array::Handle(isolate,
4408 object_store->keyword_symbols());
4409 ASSERT(!symbols.IsNull());
4410 str ^= symbols.At(kind - Token::kFirstKeyword);
4411 ASSERT(!str.IsNull());
4412 return str.raw();
4413 }
4414 return String::NewSymbol(Token::Str(kind));
4415 } else {
4416 LiteralToken& token = LiteralToken::Handle();
4417 token ^= obj.raw(); // Must be a literal token.
4418 return token.literal();
4419 }
4420 } 4370 }
4421 4371
4422 4372
4423 RawString* TokenStream::GenerateSource() const { 4373 RawString* TokenStream::GenerateSource() const {
4374 TokenStreamIterator iterator(*this, 0);
4424 GrowableObjectArray& literals = 4375 GrowableObjectArray& literals =
4425 GrowableObjectArray::Handle(GrowableObjectArray::New(Length())); 4376 GrowableObjectArray::Handle(GrowableObjectArray::New(Length()));
4426 String& literal = String::Handle(); 4377 String& literal = String::Handle();
4427 String& blank = String::Handle(String::New(" ")); 4378 String& blank = String::Handle(String::New(" "));
4428 String& newline = String::Handle(String::New("\n")); 4379 String& newline = String::Handle(String::New("\n"));
4429 for (intptr_t i = 0; i < Length(); i++) { 4380 Object& obj = Object::Handle();
4430 Token::Kind kind = KindAt(i); 4381 Token::Kind kind = iterator.CurrentTokenKind();
4431 literal = LiteralAt(i); 4382 while (kind != Token::kEOS) {
4383 obj = iterator.CurrentToken();
4384 literal = iterator.MakeLiteralToken(obj);
4432 literals.Add(literal); 4385 literals.Add(literal);
4433 if (kind == Token::kLBRACE) { 4386 if (kind == Token::kLBRACE) {
4434 literals.Add(newline); 4387 literals.Add(newline);
4435 } else { 4388 } else {
4436 literals.Add(blank); 4389 literals.Add(blank);
4437 } 4390 }
4391 iterator.Advance();
4392 kind = iterator.CurrentTokenKind();
4438 } 4393 }
4439 const Array& source = Array::Handle(Array::MakeArray(literals)); 4394 const Array& source = Array::Handle(Array::MakeArray(literals));
4440 return String::ConcatAll(source); 4395 return String::ConcatAll(source);
4441 } 4396 }
4442 4397
4443 4398
4399 intptr_t TokenStream::ComputeSourcePosition(intptr_t tok_pos) const {
4400 TokenStreamIterator iterator(*this, 0);
4401 intptr_t src_pos = 0;
4402 Token::Kind kind = iterator.CurrentTokenKind();
4403 while (iterator.CurrentPosition() < tok_pos && kind != Token::kEOS) {
4404 iterator.Advance();
4405 kind = iterator.CurrentTokenKind();
4406 src_pos += 1;
4407 }
4408 return src_pos;
4409 }
4410
4411
4444 RawTokenStream* TokenStream::New(intptr_t len) { 4412 RawTokenStream* TokenStream::New(intptr_t len) {
4445 const Class& token_stream_class = Class::Handle(Object::token_stream_class()); 4413 const Class& token_stream_class = Class::Handle(Object::token_stream_class());
4446 TokenStream& result = TokenStream::Handle(); 4414 TokenStream& result = TokenStream::Handle();
4447 { 4415 {
4448 RawObject* raw = Object::Allocate(token_stream_class, 4416 RawObject* raw = Object::Allocate(token_stream_class,
4449 TokenStream::InstanceSize(len), 4417 TokenStream::InstanceSize(len),
4450 Heap::kOld); 4418 Heap::kOld);
4451 NoGCScope no_gc; 4419 NoGCScope no_gc;
4452 result ^= raw; 4420 result ^= raw;
4453 result.SetLength(len); 4421 result.SetLength(len);
4454 } 4422 }
4455 return result.raw(); 4423 return result.raw();
4456 } 4424 }
4457 4425
4458 4426
4427 // Helper class for creation of compressed token stream data.
4428 class CompressedTokenStreamData : public ValueObject {
4429 public:
4430 CompressedTokenStreamData() :
4431 buffer_(NULL),
4432 stream_(&buffer_, Reallocate),
4433 token_objects_(GrowableObjectArray::Handle(
4434 GrowableObjectArray::New(kInitialTokenCount, Heap::kOld))),
4435 ident_obj_(Object::Handle()),
4436 literal_token_(LiteralToken::Handle()) {
4437 const String& empty_literal = String::Handle();
4438 token_objects_.Add(empty_literal);
4439 }
4440 ~CompressedTokenStreamData() {
4441 free(buffer_);
4442 }
4443
4444 // Add an IDENT token into the stream and the token objects array.
4445 void AddIdentToken(String* ident) {
4446 if (ident != NULL) {
4447 // If the IDENT token is already in the tokens object array use the
4448 // same index instead of duplicating it.
4449 intptr_t index = FindIdentIndex(ident);
4450 if (index == -1) {
4451 WriteIndex(token_objects_.Length());
4452 ASSERT(ident != NULL);
4453 token_objects_.Add(*ident);
4454 } else {
4455 WriteIndex(index);
4456 }
4457 } else {
4458 WriteIndex(0);
4459 }
4460 }
4461
4462 // Add a LITERAL token into the stream and the token objects array.
4463 void AddLiteralToken(Token::Kind kind, String* literal) {
4464 if (literal != NULL) {
4465 WriteIndex(token_objects_.Length());
4466 ASSERT(literal != NULL);
4467 literal_token_ = LiteralToken::New(kind, *literal);
4468 token_objects_.Add(literal_token_);
4469 } else {
4470 WriteIndex(0);
4471 }
4472 }
4473
4474 // Add a simple token into the stream.
4475 void AddSimpleToken(intptr_t kind) {
4476 stream_.WriteUnsigned(kind);
4477 }
4478
4479 // Return the compressed token stream length.
4480 intptr_t Length() const { return stream_.bytes_written(); }
4481
4482 // Finalize the compressed token stream by copying the stream into the
4483 // TokenStream object and setting up the token objects array.
4484 void FinalizeTokenStreamData(const TokenStream& token_stream,
4485 void* data_addr) {
4486 NoGCScope no_gc;
4487 memmove(data_addr, buffer_, Length());
4488 const Array& tokens = Array::Handle(Array::MakeArray(token_objects_));
4489 token_stream.SetTokenObjects(tokens);
4490 }
4491
4492 private:
4493 intptr_t FindIdentIndex(String* ident) {
Ivan Posva 2012/07/02 22:56:05 We should also investigate unique indices for lite
siva 2012/07/04 01:43:02 Done.
4494 ASSERT(ident != NULL);
4495 intptr_t hash_value = ident->Hash() % kTableSize;
4496 GrowableArray<intptr_t>& value = table_[hash_value];
4497 for (intptr_t i = 0; i < value.length(); i++) {
4498 intptr_t index = value[i];
4499 ident_obj_ = token_objects_.At(index);
4500 if (ident_obj_.IsString()) {
4501 const String& ident_str = String::Cast(ident_obj_);
4502 if (ident->Equals(ident_str)) {
4503 return index;
4504 }
4505 }
4506 }
4507 value.Add(token_objects_.Length());
4508 return -1;
4509 }
4510
4511 void WriteIndex(intptr_t value) {
4512 stream_.WriteUnsigned(value + Token::kNumTokens);
4513 }
4514
4515 static uint8_t* Reallocate(uint8_t* ptr,
4516 intptr_t old_size,
4517 intptr_t new_size) {
4518 void* new_ptr = ::realloc(reinterpret_cast<void*>(ptr), new_size);
4519 return reinterpret_cast<uint8_t*>(new_ptr);
4520 }
4521
4522 static const int kInitialTokenCount = 32;
4523 static const intptr_t kTableSize = 128;
4524
4525 uint8_t* buffer_;
4526 WriteStream stream_;
4527 GrowableArray<intptr_t> table_[kTableSize];
4528 const GrowableObjectArray& token_objects_;
4529 Object& ident_obj_;
4530 LiteralToken& literal_token_;
4531
4532 DISALLOW_COPY_AND_ASSIGN(CompressedTokenStreamData);
4533 };
4534
4535
4459 RawTokenStream* TokenStream::New(const Scanner::GrowableTokenStream& tokens) { 4536 RawTokenStream* TokenStream::New(const Scanner::GrowableTokenStream& tokens) {
4537 // Copy the relevant data out of the scanner into a compressed stream of
4538 // tokens.
4539 CompressedTokenStreamData data;
4460 intptr_t len = tokens.length(); 4540 intptr_t len = tokens.length();
4461
4462 TokenStream& result = TokenStream::Handle(New(len));
4463 // Copy the relevant data out of the scanner's token stream.
4464 const String& empty_literal = String::Handle();
4465 for (intptr_t i = 0; i < len; i++) { 4541 for (intptr_t i = 0; i < len; i++) {
4466 Scanner::TokenDescriptor token = tokens[i]; 4542 Scanner::TokenDescriptor token = tokens[i];
4467 if (token.literal != NULL) { 4543 if (token.kind == Token::kIDENT) { // Identifier token.
4468 result.SetTokenAt(i, token.kind, *(token.literal)); 4544 if (FLAG_compiler_stats) {
4469 } else { 4545 CompilerStats::num_ident_tokens_total += 1;
4470 result.SetTokenAt(i, token.kind, empty_literal); 4546 }
4547 data.AddIdentToken(token.literal);
4548 } else if (Token::NeedsLiteralToken(token.kind)) { // Literal token.
4549 if (FLAG_compiler_stats) {
4550 CompilerStats::num_literal_tokens_total += 1;
4551 }
4552 data.AddLiteralToken(token.kind, token.literal);
4553 } else { // Keyword, pseudo keyword etc.
4554 ASSERT(token.kind < Token::kNumTokens);
4555 data.AddSimpleToken(token.kind);
4471 } 4556 }
4472 } 4557 }
4558 if (FLAG_compiler_stats) {
4559 CompilerStats::num_tokens_total += len;
4560 }
4561 data.AddSimpleToken(Token::kEOS); // End of stream.
4562
4563 // Create and setup the token stream object.
4564 const TokenStream& result = TokenStream::Handle(New(data.Length()));
4565 data.FinalizeTokenStreamData(result, result.EntryAddr(0));
4473 return result.raw(); 4566 return result.raw();
4474 } 4567 }
4475 4568
4476 4569
4477 const char* TokenStream::ToCString() const { 4570 const char* TokenStream::ToCString() const {
4478 return "TokenStream"; 4571 return "TokenStream";
4479 } 4572 }
4480 4573
4481 4574
4575 TokenStreamIterator::TokenStreamIterator(const TokenStream& tokens,
4576 intptr_t token_pos)
4577 : tokens_(tokens),
4578 stream_(tokens.EntryAddr(0), tokens.Length()),
Ivan Posva 2012/07/02 21:48:32 This is not GC safe.
siva 2012/07/04 01:43:02 Removed the stream_ field and instead use EntryAdd
4579 token_objects_(Array::Handle(tokens.TokenObjects())),
4580 obj_(Object::Handle()),
4581 cur_token_pos_(token_pos),
4582 cur_token_kind_(Token::kILLEGAL),
4583 cur_token_obj_index_(-1) {
4584 SetCurrentPosition(token_pos);
4585 }
4586
4587
4588 bool TokenStreamIterator::IsValid() const {
4589 return !tokens_.IsNull();
4590 }
4591
4592
4593 Token::Kind TokenStreamIterator::LookaheadTokenKind(intptr_t num_tokens) {
4594 intptr_t saved_position = stream_.CurrentPosition();
4595 Token::Kind kind = Token::kILLEGAL;
4596 intptr_t value = -1;
4597 intptr_t count = 0;
4598 while (count < num_tokens && value != Token::kEOS) {
4599 value = ReadToken();
4600 count += 1;
4601 }
4602 if (value < Token::kNumTokens) {
4603 kind = static_cast<Token::Kind>(value);
4604 } else {
4605 value = value - Token::kNumTokens;
4606 obj_ = token_objects_.At(value);
4607 if (obj_.IsLiteralToken()) {
4608 const LiteralToken& literal_token = LiteralToken::Cast(obj_);
4609 kind = literal_token.kind();
4610 } else {
4611 ASSERT(obj_.IsString()); // Must be an identifier.
4612 kind = Token::kIDENT;
4613 }
4614 }
4615 stream_.SetPosition(saved_position);
4616 return kind;
4617 }
4618
4619
4620 intptr_t TokenStreamIterator::CurrentPosition() const {
4621 return cur_token_pos_;
4622 }
4623
4624
4625 void TokenStreamIterator::SetCurrentPosition(intptr_t value) {
4626 stream_.SetPosition(value);
4627 Advance();
4628 }
4629
4630
4631 void TokenStreamIterator::Advance() {
4632 cur_token_pos_ = stream_.CurrentPosition();
4633 intptr_t value = ReadToken();
4634 if (value < Token::kNumTokens) {
4635 cur_token_kind_ = static_cast<Token::Kind>(value);
4636 cur_token_obj_index_ = -1;
4637 return;
4638 }
4639 cur_token_obj_index_ = value - Token::kNumTokens;
4640 obj_ = token_objects_.At(cur_token_obj_index_);
4641 if (obj_.IsLiteralToken()) {
4642 const LiteralToken& literal_token = LiteralToken::Cast(obj_);
4643 cur_token_kind_ = literal_token.kind();
4644 return;
4645 }
4646 ASSERT(obj_.IsString()); // Must be an identifier.
4647 cur_token_kind_ = Token::kIDENT;
4648 }
4649
4650
4651 RawObject* TokenStreamIterator::CurrentToken() const {
4652 if (cur_token_obj_index_ != -1) {
4653 return token_objects_.At(cur_token_obj_index_);
4654 } else {
4655 return Smi::New(cur_token_kind_);
4656 }
4657 }
4658
4659
4660 RawString* TokenStreamIterator::CurrentLiteral() const {
4661 obj_ = CurrentToken();
4662 return MakeLiteralToken(obj_);
4663 }
4664
4665
4666 RawString* TokenStreamIterator::MakeLiteralToken(const Object& obj) const {
4667 if (obj.IsString()) {
4668 return reinterpret_cast<RawString*>(obj.raw());
4669 } else if (obj.IsSmi()) {
4670 Token::Kind kind = static_cast<Token::Kind>(
4671 Smi::Value(reinterpret_cast<RawSmi*>(obj.raw())));
4672 ASSERT(kind < Token::kNumTokens);
4673 if (Token::IsPseudoKeyword(kind) || Token::IsKeyword(kind)) {
4674 Isolate* isolate = Isolate::Current();
4675 ObjectStore* object_store = isolate->object_store();
4676 String& str = String::Handle(isolate, String::null());
4677 const Array& symbols = Array::Handle(isolate,
4678 object_store->keyword_symbols());
4679 ASSERT(!symbols.IsNull());
4680 str ^= symbols.At(kind - Token::kFirstKeyword);
4681 ASSERT(!str.IsNull());
4682 return str.raw();
4683 }
4684 return String::NewSymbol(Token::Str(kind));
4685 } else {
4686 ASSERT(obj.IsLiteralToken()); // Must be a literal token.
4687 const LiteralToken& literal_token = LiteralToken::Cast(obj);
4688 return literal_token.literal();
4689 }
4690 }
4691
4692
4482 RawString* Script::source() const { 4693 RawString* Script::source() const {
4483 String& source = String::Handle(raw_ptr()->source_); 4694 String& source = String::Handle(raw_ptr()->source_);
4484 if (source.IsNull()) { 4695 if (source.IsNull()) {
4485 const TokenStream& token_stream = TokenStream::Handle(tokens()); 4696 const TokenStream& token_stream = TokenStream::Handle(tokens());
4486 return token_stream.GenerateSource(); 4697 return token_stream.GenerateSource();
4487 } else { 4698 } else {
4488 return raw_ptr()->source_; 4699 return raw_ptr()->source_;
4489 } 4700 }
4490 } 4701 }
4491 4702
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
4526 CompilerStats::src_length += src.Length(); 4737 CompilerStats::src_length += src.Length();
4527 } 4738 }
4528 } 4739 }
4529 4740
4530 4741
4531 void Script::GetTokenLocation(intptr_t token_pos, 4742 void Script::GetTokenLocation(intptr_t token_pos,
4532 intptr_t* line, 4743 intptr_t* line,
4533 intptr_t* column) const { 4744 intptr_t* column) const {
4534 const String& src = String::Handle(source()); 4745 const String& src = String::Handle(source());
4535 const String& dummy_key = String::Handle(String::New("")); 4746 const String& dummy_key = String::Handle(String::New(""));
4747 const TokenStream& tkns = TokenStream::Handle(tokens());
4748 intptr_t src_pos = tkns.ComputeSourcePosition(token_pos);
4536 Scanner scanner(src, dummy_key); 4749 Scanner scanner(src, dummy_key);
4537 scanner.ScanTo(token_pos); 4750 scanner.ScanTo(src_pos);
4538 *line = scanner.CurrentPosition().line; 4751 *line = scanner.CurrentPosition().line;
4539 *column = scanner.CurrentPosition().column; 4752 *column = scanner.CurrentPosition().column;
4540 } 4753 }
4541 4754
4542 4755
4543 void Script::TokenRangeAtLine(intptr_t line_number, 4756 void Script::TokenRangeAtLine(intptr_t line_number,
4544 intptr_t* first_token_index, 4757 intptr_t* first_token_index,
4545 intptr_t* last_token_index) const { 4758 intptr_t* last_token_index) const {
4546 const String& src = String::Handle(source()); 4759 const String& src = String::Handle(source());
4547 const String& dummy_key = String::Handle(String::New("")); 4760 const String& dummy_key = String::Handle(String::New(""));
(...skipping 5710 matching lines...) Expand 10 before | Expand all | Expand 10 after
10258 const String& str = String::Handle(pattern()); 10471 const String& str = String::Handle(pattern());
10259 const char* format = "JSRegExp: pattern=%s flags=%s"; 10472 const char* format = "JSRegExp: pattern=%s flags=%s";
10260 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags()); 10473 intptr_t len = OS::SNPrint(NULL, 0, format, str.ToCString(), Flags());
10261 char* chars = reinterpret_cast<char*>( 10474 char* chars = reinterpret_cast<char*>(
10262 Isolate::Current()->current_zone()->Allocate(len + 1)); 10475 Isolate::Current()->current_zone()->Allocate(len + 1));
10263 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags()); 10476 OS::SNPrint(chars, (len + 1), format, str.ToCString(), Flags());
10264 return chars; 10477 return chars;
10265 } 10478 }
10266 10479
10267 } // namespace dart 10480 } // namespace dart
OLDNEW
« no previous file with comments | « vm/object.h ('k') | vm/object_test.cc » ('j') | vm/snapshot_test.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698