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

Side by Side Diff: src/runtime.cc

Issue 6240012: Optimize calls to object literal properties that are initialized with a funct... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: added x64 and arm code. Created 9 years, 10 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
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 285
286 286
287 static Handle<Object> CreateLiteralBoilerplate( 287 static Handle<Object> CreateLiteralBoilerplate(
288 Handle<FixedArray> literals, 288 Handle<FixedArray> literals,
289 Handle<FixedArray> constant_properties); 289 Handle<FixedArray> constant_properties);
290 290
291 291
292 static Handle<Object> CreateObjectLiteralBoilerplate( 292 static Handle<Object> CreateObjectLiteralBoilerplate(
293 Handle<FixedArray> literals, 293 Handle<FixedArray> literals,
294 Handle<FixedArray> constant_properties, 294 Handle<FixedArray> constant_properties,
295 bool should_have_fast_elements) { 295 bool should_have_fast_elements,
296 bool has_function_literal) {
296 // Get the global context from the literals array. This is the 297 // Get the global context from the literals array. This is the
297 // context in which the function was created and we use the object 298 // context in which the function was created and we use the object
298 // function from this context to create the object literal. We do 299 // function from this context to create the object literal. We do
299 // not use the object function from the current global context 300 // not use the object function from the current global context
300 // because this might be the object function from another context 301 // because this might be the object function from another context
301 // which we should not have access to. 302 // which we should not have access to.
302 Handle<Context> context = 303 Handle<Context> context =
303 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals)); 304 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
304 305
305 bool is_result_from_cache; 306 // In case we have function literals, we want the object to be in
306 Handle<Map> map = ComputeObjectLiteralMap(context, 307 // slow properties mode for now. We don't go in the map cache because
307 constant_properties, 308 // maps with constant functions can't be shared if the functions are
308 &is_result_from_cache); 309 // not the same (which is the common case).
310 bool is_result_from_cache = false;
311 Handle<Map> map = has_function_literal
312 ? Handle<Map>(context->object_function()->initial_map())
313 : ComputeObjectLiteralMap(context,
314 constant_properties,
315 &is_result_from_cache);
309 316
310 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map); 317 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
311 318
312 // Normalize the elements of the boilerplate to save space if needed. 319 // Normalize the elements of the boilerplate to save space if needed.
313 if (!should_have_fast_elements) NormalizeElements(boilerplate); 320 if (!should_have_fast_elements) NormalizeElements(boilerplate);
314 321
315 { // Add the constant properties to the boilerplate. 322 // Add the constant properties to the boilerplate.
316 int length = constant_properties->length(); 323 int length = constant_properties->length();
317 OptimizedObjectForAddingMultipleProperties opt(boilerplate, 324 bool should_transform =
318 length / 2, 325 !is_result_from_cache && boilerplate->HasFastProperties();
319 !is_result_from_cache); 326 if (should_transform || has_function_literal) {
320 for (int index = 0; index < length; index +=2) { 327 // Normalize the properties of object to avoid n^2 behavior
321 Handle<Object> key(constant_properties->get(index+0)); 328 // when extending the object multiple properties. Indicate the number of
322 Handle<Object> value(constant_properties->get(index+1)); 329 // properties to be added.
323 if (value->IsFixedArray()) { 330 NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
324 // The value contains the constant_properties of a 331 }
325 // simple object literal. 332
326 Handle<FixedArray> array = Handle<FixedArray>::cast(value); 333 for (int index = 0; index < length; index +=2) {
327 value = CreateLiteralBoilerplate(literals, array); 334 Handle<Object> key(constant_properties->get(index+0));
328 if (value.is_null()) return value; 335 Handle<Object> value(constant_properties->get(index+1));
329 } 336 if (value->IsFixedArray()) {
330 Handle<Object> result; 337 // The value contains the constant_properties of a
331 uint32_t element_index = 0; 338 // simple object or array literal.
332 if (key->IsSymbol()) { 339 Handle<FixedArray> array = Handle<FixedArray>::cast(value);
333 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { 340 value = CreateLiteralBoilerplate(literals, array);
334 // Array index as string (uint32). 341 if (value.is_null()) return value;
335 result = SetOwnElement(boilerplate, element_index, value); 342 }
336 } else { 343 Handle<Object> result;
337 Handle<String> name(String::cast(*key)); 344 uint32_t element_index = 0;
338 ASSERT(!name->AsArrayIndex(&element_index)); 345 if (key->IsSymbol()) {
339 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, 346 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
340 value, NONE); 347 // Array index as string (uint32).
341 }
342 } else if (key->ToArrayIndex(&element_index)) {
343 // Array index (uint32).
344 result = SetOwnElement(boilerplate, element_index, value); 348 result = SetOwnElement(boilerplate, element_index, value);
345 } else { 349 } else {
346 // Non-uint32 number. 350 Handle<String> name(String::cast(*key));
347 ASSERT(key->IsNumber()); 351 ASSERT(!name->AsArrayIndex(&element_index));
348 double num = key->Number();
349 char arr[100];
350 Vector<char> buffer(arr, ARRAY_SIZE(arr));
351 const char* str = DoubleToCString(num, buffer);
352 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
353 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, 352 result = SetLocalPropertyIgnoreAttributes(boilerplate, name,
354 value, NONE); 353 value, NONE);
355 } 354 }
356 // If setting the property on the boilerplate throws an 355 } else if (key->ToArrayIndex(&element_index)) {
357 // exception, the exception is converted to an empty handle in 356 // Array index (uint32).
358 // the handle based operations. In that case, we need to 357 result = SetOwnElement(boilerplate, element_index, value);
359 // convert back to an exception. 358 } else {
360 if (result.is_null()) return result; 359 // Non-uint32 number.
360 ASSERT(key->IsNumber());
361 double num = key->Number();
362 char arr[100];
363 Vector<char> buffer(arr, ARRAY_SIZE(arr));
364 const char* str = DoubleToCString(num, buffer);
365 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
366 result = SetLocalPropertyIgnoreAttributes(boilerplate, name,
367 value, NONE);
361 } 368 }
369 // If setting the property on the boilerplate throws an
370 // exception, the exception is converted to an empty handle in
371 // the handle based operations. In that case, we need to
372 // convert back to an exception.
373 if (result.is_null()) return result;
374 }
375
376 // Transform to fast properties if necessary. For object literals with
377 // containing function literals we defer this operation until after all
378 // computed properties have been assigned so that we can generate
379 // constant function properties.
380 if (should_transform && !has_function_literal) {
381 TransformToFastProperties(boilerplate,
382 boilerplate->map()->unused_property_fields());
362 } 383 }
363 384
364 return boilerplate; 385 return boilerplate;
365 } 386 }
366 387
367 388
368 static Handle<Object> CreateArrayLiteralBoilerplate( 389 static Handle<Object> CreateArrayLiteralBoilerplate(
369 Handle<FixedArray> literals, 390 Handle<FixedArray> literals,
370 Handle<FixedArray> elements) { 391 Handle<FixedArray> elements) {
371 // Create the JSArray. 392 // Create the JSArray.
(...skipping 10 matching lines...) Expand all
382 #ifdef DEBUG 403 #ifdef DEBUG
383 // Copy-on-write arrays must be shallow (and simple). 404 // Copy-on-write arrays must be shallow (and simple).
384 for (int i = 0; i < content->length(); i++) { 405 for (int i = 0; i < content->length(); i++) {
385 ASSERT(!content->get(i)->IsFixedArray()); 406 ASSERT(!content->get(i)->IsFixedArray());
386 } 407 }
387 #endif 408 #endif
388 } else { 409 } else {
389 for (int i = 0; i < content->length(); i++) { 410 for (int i = 0; i < content->length(); i++) {
390 if (content->get(i)->IsFixedArray()) { 411 if (content->get(i)->IsFixedArray()) {
391 // The value contains the constant_properties of a 412 // The value contains the constant_properties of a
392 // simple object literal. 413 // simple object or array literal.
393 Handle<FixedArray> fa(FixedArray::cast(content->get(i))); 414 Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
394 Handle<Object> result = 415 Handle<Object> result =
395 CreateLiteralBoilerplate(literals, fa); 416 CreateLiteralBoilerplate(literals, fa);
396 if (result.is_null()) return result; 417 if (result.is_null()) return result;
397 content->set(i, *result); 418 content->set(i, *result);
398 } 419 }
399 } 420 }
400 } 421 }
401 422
402 // Set the elements. 423 // Set the elements.
403 Handle<JSArray>::cast(object)->SetContent(*content); 424 Handle<JSArray>::cast(object)->SetContent(*content);
404 return object; 425 return object;
405 } 426 }
406 427
407 428
408 static Handle<Object> CreateLiteralBoilerplate( 429 static Handle<Object> CreateLiteralBoilerplate(
409 Handle<FixedArray> literals, 430 Handle<FixedArray> literals,
410 Handle<FixedArray> array) { 431 Handle<FixedArray> array) {
411 Handle<FixedArray> elements = CompileTimeValue::GetElements(array); 432 Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
412 switch (CompileTimeValue::GetType(array)) { 433 switch (CompileTimeValue::GetType(array)) {
413 case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS: 434 case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
414 return CreateObjectLiteralBoilerplate(literals, elements, true); 435 return CreateObjectLiteralBoilerplate(literals, elements, true, false);
415 case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS: 436 case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
416 return CreateObjectLiteralBoilerplate(literals, elements, false); 437 return CreateObjectLiteralBoilerplate(literals, elements, false, false);
417 case CompileTimeValue::ARRAY_LITERAL: 438 case CompileTimeValue::ARRAY_LITERAL:
418 return CreateArrayLiteralBoilerplate(literals, elements); 439 return CreateArrayLiteralBoilerplate(literals, elements);
419 default: 440 default:
420 UNREACHABLE(); 441 UNREACHABLE();
421 return Handle<Object>::null(); 442 return Handle<Object>::null();
422 } 443 }
423 } 444 }
424 445
425 446
426 static MaybeObject* Runtime_CreateArrayLiteralBoilerplate(Arguments args) { 447 static MaybeObject* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
(...skipping 16 matching lines...) Expand all
443 return *object; 464 return *object;
444 } 465 }
445 466
446 467
447 static MaybeObject* Runtime_CreateObjectLiteral(Arguments args) { 468 static MaybeObject* Runtime_CreateObjectLiteral(Arguments args) {
448 HandleScope scope; 469 HandleScope scope;
449 ASSERT(args.length() == 4); 470 ASSERT(args.length() == 4);
450 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 471 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
451 CONVERT_SMI_CHECKED(literals_index, args[1]); 472 CONVERT_SMI_CHECKED(literals_index, args[1]);
452 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); 473 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
453 CONVERT_SMI_CHECKED(fast_elements, args[3]); 474 CONVERT_SMI_CHECKED(flags, args[3]);
454 bool should_have_fast_elements = fast_elements == 1; 475 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
476 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
455 477
456 // Check if boilerplate exists. If not, create it first. 478 // Check if boilerplate exists. If not, create it first.
457 Handle<Object> boilerplate(literals->get(literals_index)); 479 Handle<Object> boilerplate(literals->get(literals_index));
458 if (*boilerplate == Heap::undefined_value()) { 480 if (*boilerplate == Heap::undefined_value()) {
459 boilerplate = CreateObjectLiteralBoilerplate(literals, 481 boilerplate = CreateObjectLiteralBoilerplate(literals,
460 constant_properties, 482 constant_properties,
461 should_have_fast_elements); 483 should_have_fast_elements,
484 has_function_literal);
462 if (boilerplate.is_null()) return Failure::Exception(); 485 if (boilerplate.is_null()) return Failure::Exception();
463 // Update the functions literal and return the boilerplate. 486 // Update the functions literal and return the boilerplate.
464 literals->set(literals_index, *boilerplate); 487 literals->set(literals_index, *boilerplate);
465 } 488 }
466 return DeepCopyBoilerplate(JSObject::cast(*boilerplate)); 489 return DeepCopyBoilerplate(JSObject::cast(*boilerplate));
467 } 490 }
468 491
469 492
470 static MaybeObject* Runtime_CreateObjectLiteralShallow(Arguments args) { 493 static MaybeObject* Runtime_CreateObjectLiteralShallow(Arguments args) {
471 HandleScope scope; 494 HandleScope scope;
472 ASSERT(args.length() == 4); 495 ASSERT(args.length() == 4);
473 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 496 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
474 CONVERT_SMI_CHECKED(literals_index, args[1]); 497 CONVERT_SMI_CHECKED(literals_index, args[1]);
475 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); 498 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
476 CONVERT_SMI_CHECKED(fast_elements, args[3]); 499 CONVERT_SMI_CHECKED(flags, args[3]);
477 bool should_have_fast_elements = fast_elements == 1; 500 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
501 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
478 502
479 // Check if boilerplate exists. If not, create it first. 503 // Check if boilerplate exists. If not, create it first.
480 Handle<Object> boilerplate(literals->get(literals_index)); 504 Handle<Object> boilerplate(literals->get(literals_index));
481 if (*boilerplate == Heap::undefined_value()) { 505 if (*boilerplate == Heap::undefined_value()) {
482 boilerplate = CreateObjectLiteralBoilerplate(literals, 506 boilerplate = CreateObjectLiteralBoilerplate(literals,
483 constant_properties, 507 constant_properties,
484 should_have_fast_elements); 508 should_have_fast_elements,
509 has_function_literal);
485 if (boilerplate.is_null()) return Failure::Exception(); 510 if (boilerplate.is_null()) return Failure::Exception();
486 // Update the functions literal and return the boilerplate. 511 // Update the functions literal and return the boilerplate.
487 literals->set(literals_index, *boilerplate); 512 literals->set(literals_index, *boilerplate);
488 } 513 }
489 return Heap::CopyJSObject(JSObject::cast(*boilerplate)); 514 return Heap::CopyJSObject(JSObject::cast(*boilerplate));
490 } 515 }
491 516
492 517
493 static MaybeObject* Runtime_CreateArrayLiteral(Arguments args) { 518 static MaybeObject* Runtime_CreateArrayLiteral(Arguments args) {
494 HandleScope scope; 519 HandleScope scope;
(...skipping 10375 matching lines...) Expand 10 before | Expand all | Expand 10 after
10870 } else { 10895 } else {
10871 // Handle last resort GC and make sure to allow future allocations 10896 // Handle last resort GC and make sure to allow future allocations
10872 // to grow the heap without causing GCs (if possible). 10897 // to grow the heap without causing GCs (if possible).
10873 Counters::gc_last_resort_from_js.Increment(); 10898 Counters::gc_last_resort_from_js.Increment();
10874 Heap::CollectAllGarbage(false); 10899 Heap::CollectAllGarbage(false);
10875 } 10900 }
10876 } 10901 }
10877 10902
10878 10903
10879 } } // namespace v8::internal 10904 } } // namespace v8::internal
OLDNEW
« src/hydrogen-instructions.h ('K') | « src/parser.cc ('k') | src/x64/full-codegen-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698