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

Side by Side Diff: src/builtins.cc

Issue 1815663002: Speed up PrototypeHasNoElements and drop the "fast" path before, it's now slower. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: more cleanup Created 4 years, 9 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
« no previous file with comments | « no previous file | src/objects.h » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/builtins.h" 5 #include "src/builtins.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/api-arguments.h" 8 #include "src/api-arguments.h"
9 #include "src/api-natives.h" 9 #include "src/api-natives.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 int* out) { 207 int* out) {
208 Map* arguments_map = isolate->native_context()->sloppy_arguments_map(); 208 Map* arguments_map = isolate->native_context()->sloppy_arguments_map();
209 if (object->map() != arguments_map) return false; 209 if (object->map() != arguments_map) return false;
210 DCHECK(object->HasFastElements()); 210 DCHECK(object->HasFastElements());
211 Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex); 211 Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
212 if (!len_obj->IsSmi()) return false; 212 if (!len_obj->IsSmi()) return false;
213 *out = Max(0, Smi::cast(len_obj)->value()); 213 *out = Max(0, Smi::cast(len_obj)->value());
214 return *out <= object->elements()->length(); 214 return *out <= object->elements()->length();
215 } 215 }
216 216
217 217 inline bool PrototypeHasNoElements(Isolate* isolate, JSObject* object) {
218 inline bool PrototypeHasNoElements(PrototypeIterator* iter) {
219 DisallowHeapAllocation no_gc; 218 DisallowHeapAllocation no_gc;
220 for (; !iter->IsAtEnd(); iter->Advance()) { 219 HeapObject* prototype = HeapObject::cast(object->map()->prototype());
221 if (iter->GetCurrent()->IsJSProxy()) return false; 220 HeapObject* null = isolate->heap()->null_value();
222 JSObject* current = iter->GetCurrent<JSObject>(); 221 HeapObject* empty = isolate->heap()->empty_fixed_array();
223 if (current->IsAccessCheckNeeded()) return false; 222 while (prototype != null) {
224 if (current->HasIndexedInterceptor()) return false; 223 Map* map = prototype->map();
225 if (current->HasStringWrapperElements()) return false; 224 if (map->instance_type() <= LAST_CUSTOM_ELEMENTS_RECEIVER) return false;
226 if (current->elements()->length() != 0) return false; 225 if (JSObject::cast(prototype)->elements() != empty) return false;
226 prototype = HeapObject::cast(map->prototype());
227 } 227 }
228 return true; 228 return true;
229 } 229 }
230 230
231 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, 231 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
232 JSArray* receiver) { 232 JSArray* receiver) {
233 DisallowHeapAllocation no_gc; 233 return PrototypeHasNoElements(isolate, receiver);
234 // If the array prototype chain is intact (and free of elements), and if the
235 // receiver's prototype is the array prototype, then we are done.
236 Object* prototype = receiver->map()->prototype();
237 if (prototype->IsJSArray() &&
238 isolate->is_initial_array_prototype(JSArray::cast(prototype)) &&
239 isolate->IsFastArrayConstructorPrototypeChainIntact()) {
240 return true;
241 }
242 // Slow case.
243 PrototypeIterator iter(isolate, receiver);
244 return PrototypeHasNoElements(&iter);
245 } 234 }
246 235
247 inline bool HasSimpleElements(JSObject* current) { 236 inline bool HasSimpleElements(JSObject* current) {
248 if (current->IsAccessCheckNeeded()) return false; 237 return current->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER &&
249 if (current->HasIndexedInterceptor()) return false; 238 !current->GetElementsAccessor()->HasAccessors(current);
250 if (current->HasStringWrapperElements()) return false;
251 if (current->GetElementsAccessor()->HasAccessors(current)) return false;
252 return true;
253 } 239 }
254 240
255 inline bool HasOnlySimpleReceiverElements(Isolate* isolate, 241 inline bool HasOnlySimpleReceiverElements(Isolate* isolate,
256 JSReceiver* receiver) { 242 JSObject* receiver) {
257 // Check that we have no accessors on the receiver's elements. 243 // Check that we have no accessors on the receiver's elements.
258 JSObject* object = JSObject::cast(receiver); 244 if (!HasSimpleElements(receiver)) return false;
259 if (!HasSimpleElements(object)) return false;
260 // Check that ther are not elements on the prototype. 245 // Check that ther are not elements on the prototype.
Jakob Kummerow 2016/03/21 13:24:20 drive-by nit: s/ther are not/there are no/ (or jus
261 DisallowHeapAllocation no_gc; 246 return PrototypeHasNoElements(isolate, receiver);
262 PrototypeIterator iter(isolate, receiver);
263 return PrototypeHasNoElements(&iter);
264 } 247 }
265 248
266 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) { 249 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
267 // Check that ther are not elements on the prototype. 250 // Check that ther are not elements on the prototype.
268 DisallowHeapAllocation no_gc; 251 DisallowHeapAllocation no_gc;
269 PrototypeIterator iter(isolate, receiver, 252 PrototypeIterator iter(isolate, receiver,
270 PrototypeIterator::START_AT_RECEIVER); 253 PrototypeIterator::START_AT_RECEIVER);
271 for (; !iter.IsAtEnd(); iter.Advance()) { 254 for (; !iter.IsAtEnd(); iter.Advance()) {
272 if (iter.GetCurrent()->IsJSProxy()) return false; 255 if (iter.GetCurrent()->IsJSProxy()) return false;
273 JSObject* current = iter.GetCurrent<JSObject>(); 256 JSObject* current = iter.GetCurrent<JSObject>();
274 if (!HasSimpleElements(current)) return false; 257 if (!HasSimpleElements(current)) return false;
275 } 258 }
276 return true; 259 return true;
277 } 260 }
278 261
279 // Returns |false| if not applicable. 262 // Returns |false| if not applicable.
280 MUST_USE_RESULT 263 MUST_USE_RESULT
281 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate, 264 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
282 Handle<Object> receiver, 265 Handle<Object> receiver,
283 Arguments* args, 266 Arguments* args,
284 int first_added_arg) { 267 int first_added_arg) {
285 if (!receiver->IsJSArray()) return false; 268 if (!receiver->IsJSArray()) return false;
286 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 269 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
287 // If there may be elements accessors in the prototype chain, the fast path
288 // cannot be used if there arguments to add to the array.
289 if (args != nullptr && !IsJSArrayFastElementMovingAllowed(isolate, *array)) {
290 return false;
291 }
292 ElementsKind origin_kind = array->GetElementsKind(); 270 ElementsKind origin_kind = array->GetElementsKind();
293 if (IsDictionaryElementsKind(origin_kind)) return false; 271 if (IsDictionaryElementsKind(origin_kind)) return false;
294 if (array->map()->is_observed()) return false; 272 if (array->map()->is_observed()) return false;
295 if (!array->map()->is_extensible()) return false; 273 if (!array->map()->is_extensible()) return false;
296 if (args == nullptr) return true; 274 if (args == nullptr) return true;
297 275
276 // If there may be elements accessors in the prototype chain, the fast path
277 // cannot be used if there arguments to add to the array.
278 if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false;
279
298 // Adding elements to the array prototype would break code that makes sure 280 // Adding elements to the array prototype would break code that makes sure
299 // it has no elements. Handle that elsewhere. 281 // it has no elements. Handle that elsewhere.
300 if (isolate->IsAnyInitialArrayPrototype(array)) return false; 282 if (isolate->IsAnyInitialArrayPrototype(array)) return false;
301 283
302 // Need to ensure that the arguments passed in args can be contained in 284 // Need to ensure that the arguments passed in args can be contained in
303 // the array. 285 // the array.
304 int args_length = args->length(); 286 int args_length = args->length();
305 if (first_added_arg >= args_length) return true; 287 if (first_added_arg >= args_length) return true;
306 288
307 if (IsFastObjectElementsKind(origin_kind)) return true; 289 if (IsFastObjectElementsKind(origin_kind)) return true;
308 ElementsKind target_kind = origin_kind; 290 ElementsKind target_kind = origin_kind;
309 { 291 {
310 DisallowHeapAllocation no_gc; 292 DisallowHeapAllocation no_gc;
311 int arg_count = args_length - first_added_arg; 293 for (int i = first_added_arg; i < args_length; i++) {
312 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); 294 Object* arg = (*args)[i];
313 for (int i = 0; i < arg_count; i++) {
314 Object* arg = arguments[i];
315 if (arg->IsHeapObject()) { 295 if (arg->IsHeapObject()) {
316 if (arg->IsHeapNumber()) { 296 if (arg->IsHeapNumber()) {
317 target_kind = FAST_DOUBLE_ELEMENTS; 297 target_kind = FAST_DOUBLE_ELEMENTS;
318 } else { 298 } else {
319 target_kind = FAST_ELEMENTS; 299 target_kind = FAST_ELEMENTS;
320 break; 300 break;
321 } 301 }
322 } 302 }
323 } 303 }
324 } 304 }
(...skipping 4212 matching lines...) Expand 10 before | Expand all | Expand 10 after
4537 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 4517 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
4538 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 4518 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
4539 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 4519 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
4540 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 4520 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
4541 #undef DEFINE_BUILTIN_ACCESSOR_C 4521 #undef DEFINE_BUILTIN_ACCESSOR_C
4542 #undef DEFINE_BUILTIN_ACCESSOR_A 4522 #undef DEFINE_BUILTIN_ACCESSOR_A
4543 4523
4544 4524
4545 } // namespace internal 4525 } // namespace internal
4546 } // namespace v8 4526 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698