| Index: pkg/kernel/lib/interpreter/interpreter.dart | 
| diff --git a/pkg/kernel/lib/interpreter/interpreter.dart b/pkg/kernel/lib/interpreter/interpreter.dart | 
| index abcf1a9fc59eeccb0530941087bce4fe6e007338..c956572bbdd4c87e9dcbcfe549208d1936dc8d0a 100644 | 
| --- a/pkg/kernel/lib/interpreter/interpreter.dart | 
| +++ b/pkg/kernel/lib/interpreter/interpreter.dart | 
| @@ -1032,16 +1032,22 @@ typedef void Setter(Value receiver, Value value); | 
| class Class { | 
| static final Map<Reference, Class> _classes = <Reference, Class>{}; | 
|  | 
| +  /// The immediate super class, or `null` if this is the root class object. | 
| Class superclass; | 
| -  List<Field> instanceFields = <Field>[]; | 
| -  // Implicit getters and setters for instance Fields. | 
| -  Map<Name, Getter> getters = <Name, Getter>{}; | 
| -  Map<Name, Setter> setters = <Name, Setter>{}; | 
| -  // The initializers of static fields are evaluated the first time the field | 
| -  // is accessed. | 
| -  List<Procedure> methods = <Procedure>[]; | 
|  | 
| -  int get instanceSize => instanceFields.length; | 
| +  /// The class definitions from the `implements` clause. | 
| +  final List<Supertype> interfaces = <Supertype>[]; | 
| + | 
| +  /// Implicit getters for instance fields. | 
| +  Map<Name, Getter> implicitGetters = <Name, Getter>{}; | 
| + | 
| +  /// Implicit setters for non final instance fields. | 
| +  Map<Name, Setter> implicitSetters = <Name, Setter>{}; | 
| + | 
| +  /// Instance methods, explicit getters and setters. | 
| +  Map<Name, Procedure> methods = <Name, Procedure>{}; | 
| + | 
| +  int get instanceSize => implicitGetters.length; | 
|  | 
| factory Class(Reference classRef) { | 
| return _classes.putIfAbsent( | 
| @@ -1053,69 +1059,60 @@ class Class { | 
| superclass = new Class(currentClass.superclass.reference); | 
| } | 
|  | 
| -    _populateInstanceFields(currentClass); | 
| -    // TODO: Populate methods. | 
| +    _populateImplicitGettersAndSetters(currentClass); | 
| +    _populateInstanceMethods(currentClass); | 
| } | 
|  | 
| Getter lookupImplicitGetter(Name name) { | 
| -    Getter getter = getters[name]; | 
| +    Getter getter = implicitGetters[name]; | 
| if (getter != null) return getter; | 
| if (superclass != null) return superclass.lookupImplicitGetter(name); | 
| return (Value receiver) => notImplemented(obj: name); | 
| } | 
|  | 
| Setter lookupImplicitSetter(Name name) { | 
| -    Setter setter = setters[name]; | 
| +    Setter setter = implicitSetters[name]; | 
| if (setter != null) return setter; | 
| if (superclass != null) return superclass.lookupImplicitSetter(name); | 
| return (Value receiver, Value value) => notImplemented(obj: name); | 
| } | 
|  | 
| -  Value getProperty(ObjectValue object, Member member) { | 
| -    if (member is Field) { | 
| -      int index = instanceFields.indexOf(member); | 
| -      // TODO: throw NoSuchMethodError instead. | 
| -      if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}'); | 
| -      return object.fields[index].value; | 
| -    } | 
| -    return notImplemented(obj: member); | 
| -  } | 
| - | 
| -  Value setProperty(ObjectValue object, Member member, Value value) { | 
| -    if (member is Field) { | 
| -      int index = instanceFields.indexOf(member); | 
| -      // TODO: throw NoSuchMethodError instead. | 
| -      if (index < 0) return notImplemented(m: 'NoSuchMethod: ${member}'); | 
| -      object.fields[index] = new Location(value); | 
| -      return Value.nullInstance; | 
| -    } | 
| -    return notImplemented(obj: member); | 
| -  } | 
| - | 
| -  /// Populates instance variables and the corresponding implicit getters and | 
| -  /// setters for the current class and its superclass recursively. | 
| -  _populateInstanceFields(ast.Class class_) { | 
| +  /// Populates implicit getters and setters for the current class and its | 
| +  /// superclass recursively. | 
| +  _populateImplicitGettersAndSetters(ast.Class class_) { | 
| if (class_.superclass != null) { | 
| -      _populateInstanceFields(class_.superclass); | 
| +      _populateImplicitGettersAndSetters(class_.superclass); | 
| } | 
|  | 
| for (Field f in class_.fields) { | 
| if (f.isStatic) continue; | 
| -      instanceFields.add(f); | 
| assert(f.hasImplicitGetter); | 
|  | 
| -      int currentFieldIndex = instanceFields.length - 1; | 
| - | 
| +      int currentFieldIndex = implicitGetters.length; | 
| // Shadowing an inherited getter with the same name. | 
| -      getters[f.name] = | 
| +      implicitGetters[f.name] = | 
| (Value receiver) => receiver.fields[currentFieldIndex].value; | 
| if (f.hasImplicitSetter) { | 
| // Shadowing an inherited setter with the same name. | 
| -        setters[f.name] = (Value receiver, Value value) => | 
| +        implicitSetters[f.name] = (Value receiver, Value value) => | 
| receiver.fields[currentFieldIndex] = new Location(value); | 
| } | 
| } | 
| } | 
| + | 
| +  /// Populates instance methods, getters and setters for the current class and | 
| +  /// its super class recursively. | 
| +  _populateInstanceMethods(ast.Class class_) { | 
| +    if (class_.superclass != null) { | 
| +      _populateInstanceMethods(class_.superclass); | 
| +    } | 
| + | 
| +    for (Procedure p in class_.members) { | 
| +      if (p.isStatic) continue; | 
| +      // Shadowing an inherited method, getter or setter with the same name. | 
| +      methods[p.name] = p; | 
| +    } | 
| +  } | 
| } | 
|  | 
| abstract class Value { | 
|  |