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

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: rebased and fixed lintos Created 9 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 | Annotate | Revision Log
« no previous file with comments | « src/parser.cc ('k') | src/x64/full-codegen-x64.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 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 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 static Handle<Object> CreateLiteralBoilerplate( 297 static Handle<Object> CreateLiteralBoilerplate(
298 Isolate* isolate, 298 Isolate* isolate,
299 Handle<FixedArray> literals, 299 Handle<FixedArray> literals,
300 Handle<FixedArray> constant_properties); 300 Handle<FixedArray> constant_properties);
301 301
302 302
303 static Handle<Object> CreateObjectLiteralBoilerplate( 303 static Handle<Object> CreateObjectLiteralBoilerplate(
304 Isolate* isolate, 304 Isolate* isolate,
305 Handle<FixedArray> literals, 305 Handle<FixedArray> literals,
306 Handle<FixedArray> constant_properties, 306 Handle<FixedArray> constant_properties,
307 bool should_have_fast_elements) { 307 bool should_have_fast_elements,
308 bool has_function_literal) {
308 // Get the global context from the literals array. This is the 309 // Get the global context from the literals array. This is the
309 // context in which the function was created and we use the object 310 // context in which the function was created and we use the object
310 // function from this context to create the object literal. We do 311 // function from this context to create the object literal. We do
311 // not use the object function from the current global context 312 // not use the object function from the current global context
312 // because this might be the object function from another context 313 // because this might be the object function from another context
313 // which we should not have access to. 314 // which we should not have access to.
314 Handle<Context> context = 315 Handle<Context> context =
315 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals)); 316 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
316 317
317 bool is_result_from_cache; 318 // In case we have function literals, we want the object to be in
318 Handle<Map> map = ComputeObjectLiteralMap(context, 319 // slow properties mode for now. We don't go in the map cache because
319 constant_properties, 320 // maps with constant functions can't be shared if the functions are
320 &is_result_from_cache); 321 // not the same (which is the common case).
322 bool is_result_from_cache = false;
323 Handle<Map> map = has_function_literal
324 ? Handle<Map>(context->object_function()->initial_map())
325 : ComputeObjectLiteralMap(context,
326 constant_properties,
327 &is_result_from_cache);
321 328
322 Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map); 329 Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map);
323 330
324 // Normalize the elements of the boilerplate to save space if needed. 331 // Normalize the elements of the boilerplate to save space if needed.
325 if (!should_have_fast_elements) NormalizeElements(boilerplate); 332 if (!should_have_fast_elements) NormalizeElements(boilerplate);
326 333
327 { // Add the constant properties to the boilerplate. 334 // Add the constant properties to the boilerplate.
328 int length = constant_properties->length(); 335 int length = constant_properties->length();
329 OptimizedObjectForAddingMultipleProperties opt(boilerplate, 336 bool should_transform =
330 length / 2, 337 !is_result_from_cache && boilerplate->HasFastProperties();
331 !is_result_from_cache); 338 if (should_transform || has_function_literal) {
332 for (int index = 0; index < length; index +=2) { 339 // Normalize the properties of object to avoid n^2 behavior
333 Handle<Object> key(constant_properties->get(index+0), isolate); 340 // when extending the object multiple properties. Indicate the number of
334 Handle<Object> value(constant_properties->get(index+1), isolate); 341 // properties to be added.
335 if (value->IsFixedArray()) { 342 NormalizeProperties(boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
336 // The value contains the constant_properties of a 343 }
337 // simple object literal. 344
338 Handle<FixedArray> array = Handle<FixedArray>::cast(value); 345 for (int index = 0; index < length; index +=2) {
339 value = CreateLiteralBoilerplate(isolate, literals, array); 346 Handle<Object> key(constant_properties->get(index+0), isolate);
340 if (value.is_null()) return value; 347 Handle<Object> value(constant_properties->get(index+1), isolate);
341 } 348 if (value->IsFixedArray()) {
342 Handle<Object> result; 349 // The value contains the constant_properties of a
343 uint32_t element_index = 0; 350 // simple object or array literal.
344 if (key->IsSymbol()) { 351 Handle<FixedArray> array = Handle<FixedArray>::cast(value);
345 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { 352 value = CreateLiteralBoilerplate(isolate, literals, array);
346 // Array index as string (uint32). 353 if (value.is_null()) return value;
347 result = SetOwnElement(boilerplate, 354 }
348 element_index, 355 Handle<Object> result;
349 value, 356 uint32_t element_index = 0;
350 kNonStrictMode); 357 if (key->IsSymbol()) {
351 } else { 358 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
352 Handle<String> name(String::cast(*key)); 359 // Array index as string (uint32).
353 ASSERT(!name->AsArrayIndex(&element_index));
354 result = SetLocalPropertyIgnoreAttributes(boilerplate, name,
355 value, NONE);
356 }
357 } else if (key->ToArrayIndex(&element_index)) {
358 // Array index (uint32).
359 result = SetOwnElement(boilerplate, 360 result = SetOwnElement(boilerplate,
360 element_index, 361 element_index,
361 value, 362 value,
362 kNonStrictMode); 363 kNonStrictMode);
363 } else { 364 } else {
364 // Non-uint32 number. 365 Handle<String> name(String::cast(*key));
365 ASSERT(key->IsNumber()); 366 ASSERT(!name->AsArrayIndex(&element_index));
366 double num = key->Number();
367 char arr[100];
368 Vector<char> buffer(arr, ARRAY_SIZE(arr));
369 const char* str = DoubleToCString(num, buffer);
370 Handle<String> name =
371 isolate->factory()->NewStringFromAscii(CStrVector(str));
372 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, 367 result = SetLocalPropertyIgnoreAttributes(boilerplate, name,
373 value, NONE); 368 value, NONE);
374 } 369 }
375 // If setting the property on the boilerplate throws an 370 } else if (key->ToArrayIndex(&element_index)) {
376 // exception, the exception is converted to an empty handle in 371 // Array index (uint32).
377 // the handle based operations. In that case, we need to 372 result = SetOwnElement(boilerplate,
378 // convert back to an exception. 373 element_index,
379 if (result.is_null()) return result; 374 value,
375 kNonStrictMode);
376 } else {
377 // Non-uint32 number.
378 ASSERT(key->IsNumber());
379 double num = key->Number();
380 char arr[100];
381 Vector<char> buffer(arr, ARRAY_SIZE(arr));
382 const char* str = DoubleToCString(num, buffer);
383 Handle<String> name =
384 isolate->factory()->NewStringFromAscii(CStrVector(str));
385 result = SetLocalPropertyIgnoreAttributes(boilerplate, name,
386 value, NONE);
380 } 387 }
388 // If setting the property on the boilerplate throws an
389 // exception, the exception is converted to an empty handle in
390 // the handle based operations. In that case, we need to
391 // convert back to an exception.
392 if (result.is_null()) return result;
393 }
394
395 // Transform to fast properties if necessary. For object literals with
396 // containing function literals we defer this operation until after all
397 // computed properties have been assigned so that we can generate
398 // constant function properties.
399 if (should_transform && !has_function_literal) {
400 TransformToFastProperties(boilerplate,
401 boilerplate->map()->unused_property_fields());
381 } 402 }
382 403
383 return boilerplate; 404 return boilerplate;
384 } 405 }
385 406
386 407
387 static Handle<Object> CreateArrayLiteralBoilerplate( 408 static Handle<Object> CreateArrayLiteralBoilerplate(
388 Isolate* isolate, 409 Isolate* isolate,
389 Handle<FixedArray> literals, 410 Handle<FixedArray> literals,
390 Handle<FixedArray> elements) { 411 Handle<FixedArray> elements) {
(...skipping 12 matching lines...) Expand all
403 #ifdef DEBUG 424 #ifdef DEBUG
404 // Copy-on-write arrays must be shallow (and simple). 425 // Copy-on-write arrays must be shallow (and simple).
405 for (int i = 0; i < content->length(); i++) { 426 for (int i = 0; i < content->length(); i++) {
406 ASSERT(!content->get(i)->IsFixedArray()); 427 ASSERT(!content->get(i)->IsFixedArray());
407 } 428 }
408 #endif 429 #endif
409 } else { 430 } else {
410 for (int i = 0; i < content->length(); i++) { 431 for (int i = 0; i < content->length(); i++) {
411 if (content->get(i)->IsFixedArray()) { 432 if (content->get(i)->IsFixedArray()) {
412 // The value contains the constant_properties of a 433 // The value contains the constant_properties of a
413 // simple object literal. 434 // simple object or array literal.
414 Handle<FixedArray> fa(FixedArray::cast(content->get(i))); 435 Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
415 Handle<Object> result = 436 Handle<Object> result =
416 CreateLiteralBoilerplate(isolate, literals, fa); 437 CreateLiteralBoilerplate(isolate, literals, fa);
417 if (result.is_null()) return result; 438 if (result.is_null()) return result;
418 content->set(i, *result); 439 content->set(i, *result);
419 } 440 }
420 } 441 }
421 } 442 }
422 443
423 // Set the elements. 444 // Set the elements.
424 Handle<JSArray>::cast(object)->SetContent(*content); 445 Handle<JSArray>::cast(object)->SetContent(*content);
425 return object; 446 return object;
426 } 447 }
427 448
428 449
429 static Handle<Object> CreateLiteralBoilerplate( 450 static Handle<Object> CreateLiteralBoilerplate(
430 Isolate* isolate, 451 Isolate* isolate,
431 Handle<FixedArray> literals, 452 Handle<FixedArray> literals,
432 Handle<FixedArray> array) { 453 Handle<FixedArray> array) {
433 Handle<FixedArray> elements = CompileTimeValue::GetElements(array); 454 Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
455 const bool kHasNoFunctionLiteral = false;
434 switch (CompileTimeValue::GetType(array)) { 456 switch (CompileTimeValue::GetType(array)) {
435 case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS: 457 case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
436 return CreateObjectLiteralBoilerplate(isolate, literals, elements, true); 458 return CreateObjectLiteralBoilerplate(isolate,
459 literals,
460 elements,
461 true,
462 kHasNoFunctionLiteral);
437 case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS: 463 case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
438 return CreateObjectLiteralBoilerplate(isolate, literals, elements, false); 464 return CreateObjectLiteralBoilerplate(isolate,
465 literals,
466 elements,
467 false,
468 kHasNoFunctionLiteral);
439 case CompileTimeValue::ARRAY_LITERAL: 469 case CompileTimeValue::ARRAY_LITERAL:
440 return CreateArrayLiteralBoilerplate(isolate, literals, elements); 470 return CreateArrayLiteralBoilerplate(isolate, literals, elements);
441 default: 471 default:
442 UNREACHABLE(); 472 UNREACHABLE();
443 return Handle<Object>::null(); 473 return Handle<Object>::null();
444 } 474 }
445 } 475 }
446 476
447 477
448 static MaybeObject* Runtime_CreateArrayLiteralBoilerplate( 478 static MaybeObject* Runtime_CreateArrayLiteralBoilerplate(
(...skipping 20 matching lines...) Expand all
469 } 499 }
470 500
471 501
472 static MaybeObject* Runtime_CreateObjectLiteral(RUNTIME_CALLING_CONVENTION) { 502 static MaybeObject* Runtime_CreateObjectLiteral(RUNTIME_CALLING_CONVENTION) {
473 RUNTIME_GET_ISOLATE; 503 RUNTIME_GET_ISOLATE;
474 HandleScope scope(isolate); 504 HandleScope scope(isolate);
475 ASSERT(args.length() == 4); 505 ASSERT(args.length() == 4);
476 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 506 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
477 CONVERT_SMI_CHECKED(literals_index, args[1]); 507 CONVERT_SMI_CHECKED(literals_index, args[1]);
478 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); 508 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
479 CONVERT_SMI_CHECKED(fast_elements, args[3]); 509 CONVERT_SMI_CHECKED(flags, args[3]);
480 bool should_have_fast_elements = fast_elements == 1; 510 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
511 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
481 512
482 // Check if boilerplate exists. If not, create it first. 513 // Check if boilerplate exists. If not, create it first.
483 Handle<Object> boilerplate(literals->get(literals_index), isolate); 514 Handle<Object> boilerplate(literals->get(literals_index), isolate);
484 if (*boilerplate == isolate->heap()->undefined_value()) { 515 if (*boilerplate == isolate->heap()->undefined_value()) {
485 boilerplate = CreateObjectLiteralBoilerplate(isolate, 516 boilerplate = CreateObjectLiteralBoilerplate(isolate,
486 literals, 517 literals,
487 constant_properties, 518 constant_properties,
488 should_have_fast_elements); 519 should_have_fast_elements,
520 has_function_literal);
489 if (boilerplate.is_null()) return Failure::Exception(); 521 if (boilerplate.is_null()) return Failure::Exception();
490 // Update the functions literal and return the boilerplate. 522 // Update the functions literal and return the boilerplate.
491 literals->set(literals_index, *boilerplate); 523 literals->set(literals_index, *boilerplate);
492 } 524 }
493 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); 525 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
494 } 526 }
495 527
496 528
497 static MaybeObject* Runtime_CreateObjectLiteralShallow( 529 static MaybeObject* Runtime_CreateObjectLiteralShallow(
498 RUNTIME_CALLING_CONVENTION) { 530 RUNTIME_CALLING_CONVENTION) {
499 RUNTIME_GET_ISOLATE; 531 RUNTIME_GET_ISOLATE;
500 HandleScope scope(isolate); 532 HandleScope scope(isolate);
501 ASSERT(args.length() == 4); 533 ASSERT(args.length() == 4);
502 CONVERT_ARG_CHECKED(FixedArray, literals, 0); 534 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
503 CONVERT_SMI_CHECKED(literals_index, args[1]); 535 CONVERT_SMI_CHECKED(literals_index, args[1]);
504 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2); 536 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
505 CONVERT_SMI_CHECKED(fast_elements, args[3]); 537 CONVERT_SMI_CHECKED(flags, args[3]);
506 bool should_have_fast_elements = fast_elements == 1; 538 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
539 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
507 540
508 // Check if boilerplate exists. If not, create it first. 541 // Check if boilerplate exists. If not, create it first.
509 Handle<Object> boilerplate(literals->get(literals_index), isolate); 542 Handle<Object> boilerplate(literals->get(literals_index), isolate);
510 if (*boilerplate == isolate->heap()->undefined_value()) { 543 if (*boilerplate == isolate->heap()->undefined_value()) {
511 boilerplate = CreateObjectLiteralBoilerplate(isolate, 544 boilerplate = CreateObjectLiteralBoilerplate(isolate,
512 literals, 545 literals,
513 constant_properties, 546 constant_properties,
514 should_have_fast_elements); 547 should_have_fast_elements,
548 has_function_literal);
515 if (boilerplate.is_null()) return Failure::Exception(); 549 if (boilerplate.is_null()) return Failure::Exception();
516 // Update the functions literal and return the boilerplate. 550 // Update the functions literal and return the boilerplate.
517 literals->set(literals_index, *boilerplate); 551 literals->set(literals_index, *boilerplate);
518 } 552 }
519 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate)); 553 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
520 } 554 }
521 555
522 556
523 static MaybeObject* Runtime_CreateArrayLiteral(RUNTIME_CALLING_CONVENTION) { 557 static MaybeObject* Runtime_CreateArrayLiteral(RUNTIME_CALLING_CONVENTION) {
524 RUNTIME_GET_ISOLATE; 558 RUNTIME_GET_ISOLATE;
(...skipping 11666 matching lines...) Expand 10 before | Expand all | Expand 10 after
12191 } else { 12225 } else {
12192 // Handle last resort GC and make sure to allow future allocations 12226 // Handle last resort GC and make sure to allow future allocations
12193 // to grow the heap without causing GCs (if possible). 12227 // to grow the heap without causing GCs (if possible).
12194 COUNTERS->gc_last_resort_from_js()->Increment(); 12228 COUNTERS->gc_last_resort_from_js()->Increment();
12195 HEAP->CollectAllGarbage(false); 12229 HEAP->CollectAllGarbage(false);
12196 } 12230 }
12197 } 12231 }
12198 12232
12199 12233
12200 } } // namespace v8::internal 12234 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « 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