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

Side by Side Diff: vm/parser.cc

Issue 11648006: Create read only handles for empty_array and sentinel objects (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years 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
« no previous file with comments | « vm/object_test.cc ('k') | vm/snapshot.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/parser.h" 5 #include "vm/parser.h"
6 6
7 #include "vm/bigint_operations.h" 7 #include "vm/bigint_operations.h"
8 #include "vm/class_finalizer.h" 8 #include "vm/class_finalizer.h"
9 #include "vm/compiler.h" 9 #include "vm/compiler.h"
10 #include "vm/compiler_stats.h" 10 #include "vm/compiler_stats.h"
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 // field.value = transition_sentinel; 841 // field.value = transition_sentinel;
842 // field.value = expr; 842 // field.value = expr;
843 // } 843 // }
844 // return field.value; // Type check is executed here in checked mode. 844 // return field.value; // Type check is executed here in checked mode.
845 845
846 // Generate code checking for circular dependency in field initialization. 846 // Generate code checking for circular dependency in field initialization.
847 AstNode* compare_circular = new ComparisonNode( 847 AstNode* compare_circular = new ComparisonNode(
848 TokenPos(), 848 TokenPos(),
849 Token::kEQ_STRICT, 849 Token::kEQ_STRICT,
850 new LoadStaticFieldNode(TokenPos(), field), 850 new LoadStaticFieldNode(TokenPos(), field),
851 new LiteralNode(TokenPos(), 851 new LiteralNode(TokenPos(), Object::transition_sentinel()));
852 Instance::ZoneHandle(Object::transition_sentinel())));
853 // Set field to null prior to throwing exception, so that subsequent 852 // Set field to null prior to throwing exception, so that subsequent
854 // accesses to the field do not throw again, since initializers should only 853 // accesses to the field do not throw again, since initializers should only
855 // be executed once. 854 // be executed once.
856 SequenceNode* report_circular = new SequenceNode(TokenPos(), NULL); 855 SequenceNode* report_circular = new SequenceNode(TokenPos(), NULL);
857 report_circular->Add( 856 report_circular->Add(
858 new StoreStaticFieldNode( 857 new StoreStaticFieldNode(
859 TokenPos(), 858 TokenPos(),
860 field, 859 field,
861 new LiteralNode(TokenPos(), Instance::ZoneHandle()))); 860 new LiteralNode(TokenPos(), Instance::ZoneHandle())));
862 // TODO(regis): Exception to throw is not specified by spec. 861 // TODO(regis): Exception to throw is not specified by spec.
863 const String& circular_error = String::ZoneHandle( 862 const String& circular_error = String::ZoneHandle(
864 Symbols::New("circular dependency in field initialization")); 863 Symbols::New("circular dependency in field initialization"));
865 report_circular->Add( 864 report_circular->Add(
866 new ThrowNode(TokenPos(), 865 new ThrowNode(TokenPos(),
867 new LiteralNode(TokenPos(), circular_error), 866 new LiteralNode(TokenPos(), circular_error),
868 NULL)); 867 NULL));
869 AstNode* circular_check = 868 AstNode* circular_check =
870 new IfNode(TokenPos(), compare_circular, report_circular, NULL); 869 new IfNode(TokenPos(), compare_circular, report_circular, NULL);
871 current_block_->statements->Add(circular_check); 870 current_block_->statements->Add(circular_check);
872 871
873 // Generate code checking for uninitialized field. 872 // Generate code checking for uninitialized field.
874 AstNode* compare_uninitialized = new ComparisonNode( 873 AstNode* compare_uninitialized = new ComparisonNode(
875 TokenPos(), 874 TokenPos(),
876 Token::kEQ_STRICT, 875 Token::kEQ_STRICT,
877 new LoadStaticFieldNode(TokenPos(), field), 876 new LoadStaticFieldNode(TokenPos(), field),
878 new LiteralNode(TokenPos(), 877 new LiteralNode(TokenPos(), Object::sentinel()));
879 Instance::ZoneHandle(Object::sentinel())));
880 SequenceNode* initialize_field = new SequenceNode(TokenPos(), NULL); 878 SequenceNode* initialize_field = new SequenceNode(TokenPos(), NULL);
881 initialize_field->Add( 879 initialize_field->Add(
882 new StoreStaticFieldNode( 880 new StoreStaticFieldNode(
883 TokenPos(), 881 TokenPos(),
884 field, 882 field,
885 new LiteralNode( 883 new LiteralNode(
886 TokenPos(), 884 TokenPos(), Object::transition_sentinel())));
887 Instance::ZoneHandle(Object::transition_sentinel()))));
888 // TODO(hausner): If evaluation of the field value throws an exception, 885 // TODO(hausner): If evaluation of the field value throws an exception,
889 // we leave the field value as 'transition_sentinel', which is wrong. 886 // we leave the field value as 'transition_sentinel', which is wrong.
890 // A second reference to the field later throws a circular dependency 887 // A second reference to the field later throws a circular dependency
891 // exception. The field should instead be set to null after an exception. 888 // exception. The field should instead be set to null after an exception.
892 initialize_field->Add(new StoreStaticFieldNode(TokenPos(), field, expr)); 889 initialize_field->Add(new StoreStaticFieldNode(TokenPos(), field, expr));
893 AstNode* uninitialized_check = 890 AstNode* uninitialized_check =
894 new IfNode(TokenPos(), compare_uninitialized, initialize_field, NULL); 891 new IfNode(TokenPos(), compare_uninitialized, initialize_field, NULL);
895 current_block_->statements->Add(uninitialized_check); 892 current_block_->statements->Add(uninitialized_check);
896 893
897 // Generate code returning the field value. 894 // Generate code returning the field value.
(...skipping 1812 matching lines...) Expand 10 before | Expand all | Expand 10 after
2710 } 2707 }
2711 Function& getter = Function::Handle(); 2708 Function& getter = Function::Handle();
2712 Function& setter = Function::Handle(); 2709 Function& setter = Function::Handle();
2713 Field& class_field = Field::Handle(); 2710 Field& class_field = Field::Handle();
2714 Instance& init_value = Instance::Handle(); 2711 Instance& init_value = Instance::Handle();
2715 while (true) { 2712 while (true) {
2716 bool has_initializer = CurrentToken() == Token::kASSIGN; 2713 bool has_initializer = CurrentToken() == Token::kASSIGN;
2717 bool has_simple_literal = false; 2714 bool has_simple_literal = false;
2718 if (has_initializer) { 2715 if (has_initializer) {
2719 ConsumeToken(); 2716 ConsumeToken();
2720 init_value = Object::sentinel(); 2717 init_value = Object::sentinel().raw();
2721 // For static const fields, the initialization expression 2718 // For static const fields, the initialization expression
2722 // will be parsed through the kConstImplicitGetter method 2719 // will be parsed through the kConstImplicitGetter method
2723 // invocation/compilation. 2720 // invocation/compilation.
2724 // For instance fields, the expression is parsed when a constructor 2721 // For instance fields, the expression is parsed when a constructor
2725 // is compiled. 2722 // is compiled.
2726 // For static fields with very simple initializer expressions 2723 // For static fields with very simple initializer expressions
2727 // (e.g. a literal number or string) we optimize away the 2724 // (e.g. a literal number or string) we optimize away the
2728 // kConstImplicitGetter and initialize the field here. 2725 // kConstImplicitGetter and initialize the field here.
2729 2726
2730 if (field->has_static && (field->has_final || field->has_const) && 2727 if (field->has_static && (field->has_final || field->has_const) &&
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
3098 cls ^= obj.raw(); 3095 cls ^= obj.raw();
3099 if (is_patch) { 3096 if (is_patch) {
3100 String& patch = String::Handle(Symbols::New("patch ")); 3097 String& patch = String::Handle(Symbols::New("patch "));
3101 patch = String::Concat(patch, class_name); 3098 patch = String::Concat(patch, class_name);
3102 patch = Symbols::New(patch); 3099 patch = Symbols::New(patch);
3103 cls = Class::New(patch, script_, classname_pos); 3100 cls = Class::New(patch, script_, classname_pos);
3104 cls.set_library(library_); 3101 cls.set_library(library_);
3105 } else { 3102 } else {
3106 // Not patching a class, but it has been found. This must be one of the 3103 // Not patching a class, but it has been found. This must be one of the
3107 // pre-registered classes from object.cc or a duplicate definition. 3104 // pre-registered classes from object.cc or a duplicate definition.
3108 if (cls.functions() != Object::empty_array()) { 3105 if (cls.functions() != Object::empty_array().raw()) {
3109 ErrorMsg(classname_pos, "class '%s' is already defined", 3106 ErrorMsg(classname_pos, "class '%s' is already defined",
3110 class_name.ToCString()); 3107 class_name.ToCString());
3111 } 3108 }
3112 // Pre-registered classes need their scripts connected at this time. 3109 // Pre-registered classes need their scripts connected at this time.
3113 cls.set_script(script_); 3110 cls.set_script(script_);
3114 } 3111 }
3115 } 3112 }
3116 ASSERT(!cls.IsNull()); 3113 ASSERT(!cls.IsNull());
3117 ASSERT(cls.functions() == Object::empty_array()); 3114 ASSERT(cls.functions() == Object::empty_array().raw());
3118 set_current_class(cls); 3115 set_current_class(cls);
3119 ParseTypeParameters(cls); 3116 ParseTypeParameters(cls);
3120 Type& super_type = Type::Handle(); 3117 Type& super_type = Type::Handle();
3121 if (CurrentToken() == Token::kEXTENDS) { 3118 if (CurrentToken() == Token::kEXTENDS) {
3122 ConsumeToken(); 3119 ConsumeToken();
3123 const intptr_t type_pos = TokenPos(); 3120 const intptr_t type_pos = TokenPos();
3124 const AbstractType& type = AbstractType::Handle( 3121 const AbstractType& type = AbstractType::Handle(
3125 ParseType(ClassFinalizer::kTryResolve)); 3122 ParseType(ClassFinalizer::kTryResolve));
3126 if (type.IsTypeParameter()) { 3123 if (type.IsTypeParameter()) {
3127 ErrorMsg(type_pos, 3124 ErrorMsg(type_pos,
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
3684 } 3681 }
3685 3682
3686 field = Field::New(var_name, is_static, is_final, is_const, 3683 field = Field::New(var_name, is_static, is_final, is_const,
3687 current_class(), name_pos); 3684 current_class(), name_pos);
3688 field.set_type(type); 3685 field.set_type(type);
3689 field.set_value(Instance::Handle(Instance::null())); 3686 field.set_value(Instance::Handle(Instance::null()));
3690 top_level->fields.Add(field); 3687 top_level->fields.Add(field);
3691 library_.AddObject(field, var_name); 3688 library_.AddObject(field, var_name);
3692 if (CurrentToken() == Token::kASSIGN) { 3689 if (CurrentToken() == Token::kASSIGN) {
3693 ConsumeToken(); 3690 ConsumeToken();
3694 Instance& field_value = Instance::Handle(Object::sentinel()); 3691 Instance& field_value = Instance::Handle(Object::sentinel().raw());
3695 bool has_simple_literal = false; 3692 bool has_simple_literal = false;
3696 if (is_final && (LookaheadToken(1) == Token::kSEMICOLON)) { 3693 if (is_final && (LookaheadToken(1) == Token::kSEMICOLON)) {
3697 has_simple_literal = IsSimpleLiteral(type, &field_value); 3694 has_simple_literal = IsSimpleLiteral(type, &field_value);
3698 } 3695 }
3699 SkipExpr(); 3696 SkipExpr();
3700 field.set_value(field_value); 3697 field.set_value(field_value);
3701 if (!has_simple_literal) { 3698 if (!has_simple_literal) {
3702 // Create a static const getter. 3699 // Create a static const getter.
3703 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name)); 3700 String& getter_name = String::ZoneHandle(Field::GetterSymbol(var_name));
3704 getter = Function::New(getter_name, 3701 getter = Function::New(getter_name,
(...skipping 3496 matching lines...) Expand 10 before | Expand all | Expand 10 after
7201 // If the static field has an initializer, initialize the field at compile 7198 // If the static field has an initializer, initialize the field at compile
7202 // time, which is only possible if the field is const. 7199 // time, which is only possible if the field is const.
7203 AstNode* initializing_getter = RunStaticFieldInitializer(field); 7200 AstNode* initializing_getter = RunStaticFieldInitializer(field);
7204 if (initializing_getter != NULL) { 7201 if (initializing_getter != NULL) {
7205 // The field is not yet initialized and could not be initialized at compile 7202 // The field is not yet initialized and could not be initialized at compile
7206 // time. The getter will initialize the field. 7203 // time. The getter will initialize the field.
7207 return initializing_getter; 7204 return initializing_getter;
7208 } 7205 }
7209 // The field is initialized. 7206 // The field is initialized.
7210 if (field.is_const()) { 7207 if (field.is_const()) {
7211 ASSERT(field.value() != Object::sentinel()); 7208 ASSERT(field.value() != Object::sentinel().raw());
7212 ASSERT(field.value() != Object::transition_sentinel()); 7209 ASSERT(field.value() != Object::transition_sentinel().raw());
7213 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value())); 7210 return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value()));
7214 } 7211 }
7215 // Access the field directly. 7212 // Access the field directly.
7216 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw())); 7213 return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw()));
7217 } 7214 }
7218 7215
7219 7216
7220 AstNode* Parser::ParseStaticFieldAccess(const Class& cls, 7217 AstNode* Parser::ParseStaticFieldAccess(const Class& cls,
7221 const String& field_name, 7218 const String& field_name,
7222 intptr_t ident_pos, 7219 intptr_t ident_pos,
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
7815 return current_class().NumTypeParameters() > 0; 7812 return current_class().NumTypeParameters() > 0;
7816 } 7813 }
7817 7814
7818 7815
7819 // If the field is already initialized, return no ast (NULL). 7816 // If the field is already initialized, return no ast (NULL).
7820 // Otherwise, if the field is constant, initialize the field and return no ast. 7817 // Otherwise, if the field is constant, initialize the field and return no ast.
7821 // If the field is not initialized and not const, return the ast for the getter. 7818 // If the field is not initialized and not const, return the ast for the getter.
7822 AstNode* Parser::RunStaticFieldInitializer(const Field& field) { 7819 AstNode* Parser::RunStaticFieldInitializer(const Field& field) {
7823 ASSERT(field.is_static()); 7820 ASSERT(field.is_static());
7824 const Instance& value = Instance::Handle(field.value()); 7821 const Instance& value = Instance::Handle(field.value());
7825 if (value.raw() == Object::transition_sentinel()) { 7822 if (value.raw() == Object::transition_sentinel().raw()) {
7826 if (field.is_const()) { 7823 if (field.is_const()) {
7827 ErrorMsg("circular dependency while initializing static field '%s'", 7824 ErrorMsg("circular dependency while initializing static field '%s'",
7828 String::Handle(field.name()).ToCString()); 7825 String::Handle(field.name()).ToCString());
7829 } else { 7826 } else {
7830 // The implicit static getter will throw the exception if necessary. 7827 // The implicit static getter will throw the exception if necessary.
7831 return new StaticGetterNode(TokenPos(), 7828 return new StaticGetterNode(TokenPos(),
7832 NULL, 7829 NULL,
7833 false, 7830 false,
7834 Class::ZoneHandle(field.owner()), 7831 Class::ZoneHandle(field.owner()),
7835 String::ZoneHandle(field.name())); 7832 String::ZoneHandle(field.name()));
7836 } 7833 }
7837 } else if (value.raw() == Object::sentinel()) { 7834 } else if (value.raw() == Object::sentinel().raw()) {
7838 // This field has not been referenced yet and thus the value has 7835 // This field has not been referenced yet and thus the value has
7839 // not been evaluated. If the field is const, call the static getter method 7836 // not been evaluated. If the field is const, call the static getter method
7840 // to evaluate the expression and canonicalize the value. 7837 // to evaluate the expression and canonicalize the value.
7841 if (field.is_const()) { 7838 if (field.is_const()) {
7842 field.set_value(Instance::Handle(Object::transition_sentinel())); 7839 field.set_value(Object::transition_sentinel());
7843 const String& field_name = String::Handle(field.name()); 7840 const String& field_name = String::Handle(field.name());
7844 const String& getter_name = 7841 const String& getter_name =
7845 String::Handle(Field::GetterName(field_name)); 7842 String::Handle(Field::GetterName(field_name));
7846 const Class& cls = Class::Handle(field.owner()); 7843 const Class& cls = Class::Handle(field.owner());
7847 const int kNumArguments = 0; // no arguments. 7844 const int kNumArguments = 0; // no arguments.
7848 const Array& kNoArgumentNames = Array::Handle(); 7845 const Array& kNoArgumentNames = Array::Handle();
7849 const Function& func = 7846 const Function& func =
7850 Function::Handle(Resolver::ResolveStatic(cls, 7847 Function::Handle(Resolver::ResolveStatic(cls,
7851 getter_name, 7848 getter_name,
7852 kNumArguments, 7849 kNumArguments,
7853 kNoArgumentNames, 7850 kNoArgumentNames,
7854 Resolver::kIsQualified)); 7851 Resolver::kIsQualified));
7855 ASSERT(!func.IsNull()); 7852 ASSERT(!func.IsNull());
7856 ASSERT(func.kind() == RawFunction::kConstImplicitGetter); 7853 ASSERT(func.kind() == RawFunction::kConstImplicitGetter);
7857 const Array& args = Array::Handle(Object::empty_array()); 7854 Object& const_value = Object::Handle(
7858 Object& const_value = Object::Handle(DartEntry::InvokeStatic(func, args)); 7855 DartEntry::InvokeStatic(func, Object::empty_array()));
7859 if (const_value.IsError()) { 7856 if (const_value.IsError()) {
7860 const Error& error = Error::Cast(const_value); 7857 const Error& error = Error::Cast(const_value);
7861 if (error.IsUnhandledException()) { 7858 if (error.IsUnhandledException()) {
7862 field.set_value(Instance::Handle()); 7859 field.set_value(Instance::Handle());
7863 // It is a compile-time error if evaluation of a compile-time constant 7860 // It is a compile-time error if evaluation of a compile-time constant
7864 // would raise an exception. 7861 // would raise an exception.
7865 AppendErrorMsg(error, TokenPos(), 7862 AppendErrorMsg(error, TokenPos(),
7866 "error initializing const field '%s'", 7863 "error initializing const field '%s'",
7867 String::Handle(field.name()).ToCString()); 7864 String::Handle(field.name()).ToCString());
7868 } else { 7865 } else {
(...skipping 1828 matching lines...) Expand 10 before | Expand all | Expand 10 after
9697 void Parser::SkipQualIdent() { 9694 void Parser::SkipQualIdent() {
9698 ASSERT(IsIdentifier()); 9695 ASSERT(IsIdentifier());
9699 ConsumeToken(); 9696 ConsumeToken();
9700 if (CurrentToken() == Token::kPERIOD) { 9697 if (CurrentToken() == Token::kPERIOD) {
9701 ConsumeToken(); // Consume the kPERIOD token. 9698 ConsumeToken(); // Consume the kPERIOD token.
9702 ExpectIdentifier("identifier expected after '.'"); 9699 ExpectIdentifier("identifier expected after '.'");
9703 } 9700 }
9704 } 9701 }
9705 9702
9706 } // namespace dart 9703 } // namespace dart
OLDNEW
« no previous file with comments | « vm/object_test.cc ('k') | vm/snapshot.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698