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

Side by Side Diff: runtime/vm/code_generator.cc

Issue 14238036: Improve type optimization reusing the type argument vector of the instantiator (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 8 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
« no previous file with comments | « no previous file | runtime/vm/flow_graph_optimizer.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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/code_generator.h" 5 #include "vm/code_generator.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.h"
8 #include "vm/ast.h" 8 #include "vm/ast.h"
9 #include "vm/bigint_operations.h" 9 #include "vm/bigint_operations.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 // Arg0: array length. 91 // Arg0: array length.
92 // Arg1: array type arguments, i.e. vector of 1 type, the element type. 92 // Arg1: array type arguments, i.e. vector of 1 type, the element type.
93 // Return value: newly allocated array of length arg0. 93 // Return value: newly allocated array of length arg0.
94 DEFINE_RUNTIME_ENTRY(AllocateArray, 2) { 94 DEFINE_RUNTIME_ENTRY(AllocateArray, 2) {
95 ASSERT(arguments.ArgCount() == kAllocateArrayRuntimeEntry.argument_count()); 95 ASSERT(arguments.ArgCount() == kAllocateArrayRuntimeEntry.argument_count());
96 const Smi& length = Smi::CheckedHandle(arguments.ArgAt(0)); 96 const Smi& length = Smi::CheckedHandle(arguments.ArgAt(0));
97 const Array& array = Array::Handle(Array::New(length.Value())); 97 const Array& array = Array::Handle(Array::New(length.Value()));
98 arguments.SetReturn(array); 98 arguments.SetReturn(array);
99 AbstractTypeArguments& element_type = 99 AbstractTypeArguments& element_type =
100 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 100 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
101 // An Array is raw or takes only one type argument. 101 // An Array is raw or takes one type argument. However, its type argument
102 // vector may be longer than 1 due to a type optimization reusing the type
103 // argument vector of the instantiator.
102 ASSERT(element_type.IsNull() || 104 ASSERT(element_type.IsNull() ||
103 ((element_type.Length() == 1) && element_type.IsInstantiated())); 105 ((element_type.Length() >= 1) && element_type.IsInstantiated()));
104 array.SetTypeArguments(element_type); // May be null. 106 array.SetTypeArguments(element_type); // May be null.
105 } 107 }
106 108
107 109
108 // Allocate a new object. 110 // Allocate a new object.
109 // Arg0: class of the object that needs to be allocated. 111 // Arg0: class of the object that needs to be allocated.
110 // Arg1: type arguments of the object that needs to be allocated. 112 // Arg1: type arguments of the object that needs to be allocated.
111 // Arg2: type arguments of the instantiator or kNoInstantiator. 113 // Arg2: type arguments of the instantiator or kNoInstantiator.
112 // Return value: newly allocated object. 114 // Return value: newly allocated object.
113 DEFINE_RUNTIME_ENTRY(AllocateObject, 3) { 115 DEFINE_RUNTIME_ENTRY(AllocateObject, 3) {
114 ASSERT(arguments.ArgCount() == kAllocateObjectRuntimeEntry.argument_count()); 116 ASSERT(arguments.ArgCount() == kAllocateObjectRuntimeEntry.argument_count());
115 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0)); 117 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0));
116 const Instance& instance = Instance::Handle(Instance::New(cls)); 118 const Instance& instance = Instance::Handle(Instance::New(cls));
117 arguments.SetReturn(instance); 119 arguments.SetReturn(instance);
118 if (!cls.HasTypeArguments()) { 120 if (!cls.HasTypeArguments()) {
119 // No type arguments required for a non-parameterized type. 121 // No type arguments required for a non-parameterized type.
120 ASSERT(Instance::CheckedHandle(arguments.ArgAt(1)).IsNull()); 122 ASSERT(Instance::CheckedHandle(arguments.ArgAt(1)).IsNull());
121 return; 123 return;
122 } 124 }
123 AbstractTypeArguments& type_arguments = 125 AbstractTypeArguments& type_arguments =
124 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 126 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
125 ASSERT(type_arguments.IsNull() ||
126 (type_arguments.Length() == cls.NumTypeArguments()));
127 // If no instantiator is provided, set the type arguments and return. 127 // If no instantiator is provided, set the type arguments and return.
128 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) { 128 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
129 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() == 129 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
130 StubCode::kNoInstantiator); 130 StubCode::kNoInstantiator);
131 // Unless null (for a raw type), the type argument vector may be longer than
132 // necessary due to a type optimization reusing the type argument vector of
133 // the instantiator.
134 ASSERT(type_arguments.IsNull() ||
135 (type_arguments.IsInstantiated() &&
136 (type_arguments.Length() >= cls.NumTypeArguments())));
131 instance.SetTypeArguments(type_arguments); // May be null. 137 instance.SetTypeArguments(type_arguments); // May be null.
132 return; 138 return;
133 } 139 }
134 ASSERT(!type_arguments.IsInstantiated()); 140 // A still uninstantiated type argument vector must have the correct length.
141 ASSERT(!type_arguments.IsInstantiated() &&
142 (type_arguments.Length() == cls.NumTypeArguments()));
135 const AbstractTypeArguments& instantiator = 143 const AbstractTypeArguments& instantiator =
136 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2)); 144 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
137 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 145 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
138 if (instantiator.IsNull()) { 146 // Code inlined in the caller should have optimized the case where the
139 type_arguments = 147 // instantiator can be reused as type argument vector.
140 InstantiatedTypeArguments::New(type_arguments, instantiator); 148 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
141 } else if (instantiator.IsTypeArguments()) { 149 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator);
142 // Code inlined in the caller should have optimized the case where the
143 // instantiator is a TypeArguments and can be used as type argument vector.
144 ASSERT(!type_arguments.IsUninstantiatedIdentity() ||
145 (instantiator.Length() != type_arguments.Length()));
146 type_arguments =
147 InstantiatedTypeArguments::New(type_arguments, instantiator);
148 } else {
149 // If possible, use the instantiator as the type argument vector.
150 if (type_arguments.IsUninstantiatedIdentity() &&
151 (instantiator.Length() == type_arguments.Length())) {
152 type_arguments = instantiator.raw();
153 } else {
154 type_arguments =
155 InstantiatedTypeArguments::New(type_arguments, instantiator);
156 }
157 }
158 ASSERT(type_arguments.IsInstantiated());
159 instance.SetTypeArguments(type_arguments); 150 instance.SetTypeArguments(type_arguments);
160 } 151 }
161 152
162 153
163 // Helper returning the token position of the Dart caller. 154 // Helper returning the token position of the Dart caller.
164 static intptr_t GetCallerLocation() { 155 static intptr_t GetCallerLocation() {
165 DartFrameIterator iterator; 156 DartFrameIterator iterator;
166 StackFrame* caller_frame = iterator.NextFrame(); 157 StackFrame* caller_frame = iterator.NextFrame();
167 ASSERT(caller_frame != NULL); 158 ASSERT(caller_frame != NULL);
168 return caller_frame->GetTokenPos(); 159 return caller_frame->GetTokenPos();
169 } 160 }
170 161
171 162
172 // Allocate a new object of a generic type and check that the instantiated type 163 // Allocate a new object of a generic type and check that the instantiated type
173 // arguments are within the declared bounds or throw a dynamic type error. 164 // arguments are within the declared bounds or throw a dynamic type error.
174 // Arg0: class of the object that needs to be allocated. 165 // Arg0: class of the object that needs to be allocated.
175 // Arg1: type arguments of the object that needs to be allocated. 166 // Arg1: type arguments of the object that needs to be allocated.
176 // Arg2: type arguments of the instantiator or kNoInstantiator. 167 // Arg2: type arguments of the instantiator or kNoInstantiator.
177 // Return value: newly allocated object. 168 // Return value: newly allocated object.
178 DEFINE_RUNTIME_ENTRY(AllocateObjectWithBoundsCheck, 3) { 169 DEFINE_RUNTIME_ENTRY(AllocateObjectWithBoundsCheck, 3) {
179 ASSERT(FLAG_enable_type_checks); 170 ASSERT(FLAG_enable_type_checks);
180 ASSERT(arguments.ArgCount() == 171 ASSERT(arguments.ArgCount() ==
181 kAllocateObjectWithBoundsCheckRuntimeEntry.argument_count()); 172 kAllocateObjectWithBoundsCheckRuntimeEntry.argument_count());
182 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0)); 173 const Class& cls = Class::CheckedHandle(arguments.ArgAt(0));
183 const Instance& instance = Instance::Handle(Instance::New(cls)); 174 const Instance& instance = Instance::Handle(Instance::New(cls));
184 arguments.SetReturn(instance); 175 arguments.SetReturn(instance);
185 ASSERT(cls.HasTypeArguments()); 176 ASSERT(cls.HasTypeArguments());
186 AbstractTypeArguments& type_arguments = 177 AbstractTypeArguments& type_arguments =
187 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 178 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
188 ASSERT(type_arguments.IsNull() ||
189 (type_arguments.Length() == cls.NumTypeArguments()));
190 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) { 179 if (Object::Handle(arguments.ArgAt(2)).IsSmi()) {
191 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() == 180 ASSERT(Smi::CheckedHandle(arguments.ArgAt(2)).Value() ==
192 StubCode::kNoInstantiator); 181 StubCode::kNoInstantiator);
182 // Unless null (for a raw type), the type argument vector may be longer than
183 // necessary due to a type optimization reusing the type argument vector of
184 // the instantiator.
185 ASSERT(type_arguments.IsNull() ||
186 (type_arguments.IsInstantiated() &&
187 (type_arguments.Length() >= cls.NumTypeArguments())));
193 } else { 188 } else {
194 ASSERT(!type_arguments.IsInstantiated()); 189 // A still uninstantiated type argument vector must have the correct length.
190 ASSERT(!type_arguments.IsInstantiated() &&
191 (type_arguments.Length() == cls.NumTypeArguments()));
195 const AbstractTypeArguments& instantiator = 192 const AbstractTypeArguments& instantiator =
196 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2)); 193 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(2));
197 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 194 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
198 Error& malformed_error = Error::Handle(); 195 Error& malformed_error = Error::Handle();
199 if (instantiator.IsNull()) { 196 // Code inlined in the caller should have optimized the case where the
200 type_arguments = type_arguments.InstantiateFrom(instantiator, 197 // instantiator can be reused as type argument vector.
201 &malformed_error); 198 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
202 } else if (instantiator.IsTypeArguments()) { 199 type_arguments = type_arguments.InstantiateFrom(instantiator,
203 // Code inlined in the caller should have optimized the case where the 200 &malformed_error);
204 // instantiator is a TypeArguments and can be used as type argument
205 // vector.
206 ASSERT(!type_arguments.IsUninstantiatedIdentity() ||
207 (instantiator.Length() != type_arguments.Length()));
208 type_arguments = type_arguments.InstantiateFrom(instantiator,
209 &malformed_error);
210 } else {
211 // If possible, use the instantiator as the type argument vector.
212 if (type_arguments.IsUninstantiatedIdentity() &&
213 (instantiator.Length() == type_arguments.Length())) {
214 type_arguments = instantiator.raw();
215 } else {
216 type_arguments = type_arguments.InstantiateFrom(instantiator,
217 &malformed_error);
218 }
219 }
220 if (!malformed_error.IsNull()) { 201 if (!malformed_error.IsNull()) {
221 // Throw a dynamic type error. 202 // Throw a dynamic type error.
222 const intptr_t location = GetCallerLocation(); 203 const intptr_t location = GetCallerLocation();
223 String& malformed_error_message = String::Handle( 204 String& malformed_error_message = String::Handle(
224 String::New(malformed_error.ToErrorCString())); 205 String::New(malformed_error.ToErrorCString()));
225 Exceptions::CreateAndThrowTypeError( 206 Exceptions::CreateAndThrowTypeError(
226 location, Symbols::Empty(), Symbols::Empty(), 207 location, Symbols::Empty(), Symbols::Empty(),
227 Symbols::Empty(), malformed_error_message); 208 Symbols::Empty(), malformed_error_message);
228 UNREACHABLE(); 209 UNREACHABLE();
229 } 210 }
(...skipping 10 matching lines...) Expand all
240 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) { 221 DEFINE_RUNTIME_ENTRY(InstantiateTypeArguments, 2) {
241 ASSERT(arguments.ArgCount() == 222 ASSERT(arguments.ArgCount() ==
242 kInstantiateTypeArgumentsRuntimeEntry.argument_count()); 223 kInstantiateTypeArgumentsRuntimeEntry.argument_count());
243 AbstractTypeArguments& type_arguments = 224 AbstractTypeArguments& type_arguments =
244 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(0)); 225 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(0));
245 const AbstractTypeArguments& instantiator = 226 const AbstractTypeArguments& instantiator =
246 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1)); 227 AbstractTypeArguments::CheckedHandle(arguments.ArgAt(1));
247 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated()); 228 ASSERT(!type_arguments.IsNull() && !type_arguments.IsInstantiated());
248 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated()); 229 ASSERT(instantiator.IsNull() || instantiator.IsInstantiated());
249 // Code inlined in the caller should have optimized the case where the 230 // Code inlined in the caller should have optimized the case where the
250 // instantiator can be used as type argument vector. 231 // instantiator can be reused as type argument vector.
251 ASSERT(instantiator.IsNull() || 232 ASSERT(instantiator.IsNull() || !type_arguments.IsUninstantiatedIdentity());
252 !type_arguments.IsUninstantiatedIdentity() ||
253 !instantiator.IsTypeArguments() ||
254 (instantiator.Length() != type_arguments.Length()));
255 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator); 233 type_arguments = InstantiatedTypeArguments::New(type_arguments, instantiator);
256 ASSERT(type_arguments.IsInstantiated()); 234 ASSERT(type_arguments.IsInstantiated());
257 arguments.SetReturn(type_arguments); 235 arguments.SetReturn(type_arguments);
258 } 236 }
259 237
260 238
261 // Allocate a new closure. 239 // Allocate a new closure.
262 // The type argument vector of a closure is always the vector of type parameters 240 // The type argument vector of a closure is always the vector of type parameters
263 // of its signature class, i.e. an uninstantiated identity vector. Therefore, 241 // of its signature class, i.e. an uninstantiated identity vector. Therefore,
264 // the instantiator type arguments can be used as the instantiated closure type 242 // the instantiator type arguments can be used as the instantiated closure type
(...skipping 1452 matching lines...) Expand 10 before | Expand all | Expand 10 after
1717 // Arg1: Value that is being stored. 1695 // Arg1: Value that is being stored.
1718 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { 1696 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) {
1719 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); 1697 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count());
1720 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); 1698 const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
1721 const Object& value = Object::Handle(arguments.ArgAt(1)); 1699 const Object& value = Object::Handle(arguments.ArgAt(1));
1722 1700
1723 field.UpdateCid(Class::Handle(value.clazz()).id()); 1701 field.UpdateCid(Class::Handle(value.clazz()).id());
1724 } 1702 }
1725 1703
1726 } // namespace dart 1704 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_optimizer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698