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

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: 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; 245 return PrototypeHasNoElements(isolate, receiver);
260 // Check that ther are not elements on the prototype.
261 DisallowHeapAllocation no_gc;
262 PrototypeIterator iter(isolate, receiver);
263 return PrototypeHasNoElements(&iter);
264 } 246 }
265 247
266 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) { 248 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) {
267 // Check that ther are not elements on the prototype.
268 DisallowHeapAllocation no_gc; 249 DisallowHeapAllocation no_gc;
269 PrototypeIterator iter(isolate, receiver, 250 PrototypeIterator iter(isolate, receiver,
270 PrototypeIterator::START_AT_RECEIVER); 251 PrototypeIterator::START_AT_RECEIVER);
271 for (; !iter.IsAtEnd(); iter.Advance()) { 252 for (; !iter.IsAtEnd(); iter.Advance()) {
272 if (iter.GetCurrent()->IsJSProxy()) return false; 253 if (iter.GetCurrent()->IsJSProxy()) return false;
273 JSObject* current = iter.GetCurrent<JSObject>(); 254 JSObject* current = iter.GetCurrent<JSObject>();
274 if (!HasSimpleElements(current)) return false; 255 if (!HasSimpleElements(current)) return false;
275 } 256 }
276 return true; 257 return true;
277 } 258 }
278 259
279 // Returns |false| if not applicable. 260 // Returns |false| if not applicable.
280 MUST_USE_RESULT 261 MUST_USE_RESULT
281 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate, 262 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate,
282 Handle<Object> receiver, 263 Handle<Object> receiver,
283 Arguments* args, 264 Arguments* args,
284 int first_added_arg) { 265 int first_added_arg) {
285 if (!receiver->IsJSArray()) return false; 266 if (!receiver->IsJSArray()) return false;
286 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 267 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(); 268 ElementsKind origin_kind = array->GetElementsKind();
293 if (IsDictionaryElementsKind(origin_kind)) return false; 269 if (IsDictionaryElementsKind(origin_kind)) return false;
294 if (array->map()->is_observed()) return false; 270 if (array->map()->is_observed()) return false;
295 if (!array->map()->is_extensible()) return false; 271 if (!array->map()->is_extensible()) return false;
296 if (args == nullptr) return true; 272 if (args == nullptr) return true;
297 273
274 // If there may be elements accessors in the prototype chain, the fast path
275 // cannot be used if there arguments to add to the array.
276 if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false;
277
298 // Adding elements to the array prototype would break code that makes sure 278 // Adding elements to the array prototype would break code that makes sure
299 // it has no elements. Handle that elsewhere. 279 // it has no elements. Handle that elsewhere.
300 if (isolate->IsAnyInitialArrayPrototype(array)) return false; 280 if (isolate->IsAnyInitialArrayPrototype(array)) return false;
301 281
302 // Need to ensure that the arguments passed in args can be contained in 282 // Need to ensure that the arguments passed in args can be contained in
303 // the array. 283 // the array.
304 int args_length = args->length(); 284 int args_length = args->length();
305 if (first_added_arg >= args_length) return true; 285 if (first_added_arg >= args_length) return true;
306 286
307 if (IsFastObjectElementsKind(origin_kind)) return true; 287 if (IsFastObjectElementsKind(origin_kind)) return true;
308 ElementsKind target_kind = origin_kind; 288 ElementsKind target_kind = origin_kind;
309 { 289 {
310 DisallowHeapAllocation no_gc; 290 DisallowHeapAllocation no_gc;
311 int arg_count = args_length - first_added_arg; 291 for (int i = first_added_arg; i < args_length; i++) {
312 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); 292 Object* arg = (*args)[i];
313 for (int i = 0; i < arg_count; i++) {
314 Object* arg = arguments[i];
315 if (arg->IsHeapObject()) { 293 if (arg->IsHeapObject()) {
316 if (arg->IsHeapNumber()) { 294 if (arg->IsHeapNumber()) {
317 target_kind = FAST_DOUBLE_ELEMENTS; 295 target_kind = FAST_DOUBLE_ELEMENTS;
318 } else { 296 } else {
319 target_kind = FAST_ELEMENTS; 297 target_kind = FAST_ELEMENTS;
320 break; 298 break;
321 } 299 }
322 } 300 }
323 } 301 }
324 } 302 }
(...skipping 4212 matching lines...) Expand 10 before | Expand all | Expand 10 after
4537 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 4515 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
4538 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 4516 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
4539 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 4517 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
4540 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 4518 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
4541 #undef DEFINE_BUILTIN_ACCESSOR_C 4519 #undef DEFINE_BUILTIN_ACCESSOR_C
4542 #undef DEFINE_BUILTIN_ACCESSOR_A 4520 #undef DEFINE_BUILTIN_ACCESSOR_A
4543 4521
4544 4522
4545 } // namespace internal 4523 } // namespace internal
4546 } // namespace v8 4524 } // 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