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

Side by Side Diff: src/runtime.cc

Issue 9443014: Fix redefinition of aliased elements in arguments. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments by Sven Panne. Created 8 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
« no previous file with comments | « src/objects.cc ('k') | test/cctest/test-api.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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 4337 matching lines...) Expand 10 before | Expand all | Expand 10 after
4348 ASSERT(args.length() == 4); 4348 ASSERT(args.length() == 4);
4349 HandleScope scope(isolate); 4349 HandleScope scope(isolate);
4350 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); 4350 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4351 CONVERT_ARG_HANDLE_CHECKED(String, name, 1); 4351 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4352 Handle<Object> obj_value = args.at<Object>(2); 4352 Handle<Object> obj_value = args.at<Object>(2);
4353 CONVERT_SMI_ARG_CHECKED(unchecked, 3); 4353 CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4354 4354
4355 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); 4355 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4356 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); 4356 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4357 4357
4358 // Check if this is an element.
4359 uint32_t index;
4360 bool is_element = name->AsArrayIndex(&index);
4361
4362 // Special case for elements if any of the flags might be involved.
4363 // If elements are in fast case we always implicitly assume that:
4364 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false.
4365 if (is_element && (attr != NONE ||
4366 js_object->HasLocalElement(index) == JSObject::DICTIONARY_ELEMENT)) {
4367 // Normalize the elements to enable attributes on the property.
4368 if (js_object->IsJSGlobalProxy()) {
4369 // We do not need to do access checks here since these has already
4370 // been performed by the call to GetOwnProperty.
4371 Handle<Object> proto(js_object->GetPrototype());
4372 // If proxy is detached, ignore the assignment. Alternatively,
4373 // we could throw an exception.
4374 if (proto->IsNull()) return *obj_value;
4375 js_object = Handle<JSObject>::cast(proto);
4376 }
4377
4378 // Don't allow element properties to be redefined on objects with external
4379 // array elements.
4380 if (js_object->HasExternalArrayElements()) {
4381 Handle<Object> args[2] = { js_object, name };
4382 Handle<Object> error =
4383 isolate->factory()->NewTypeError("redef_external_array_element",
4384 HandleVector(args, 2));
4385 return isolate->Throw(*error);
4386 }
4387
4388 Handle<SeededNumberDictionary> dictionary =
4389 JSObject::NormalizeElements(js_object);
4390 // Make sure that we never go back to fast case.
4391 dictionary->set_requires_slow_elements();
4392 PropertyDetails details = PropertyDetails(attr, NORMAL);
4393 Handle<SeededNumberDictionary> extended_dictionary =
4394 SeededNumberDictionary::Set(dictionary, index, obj_value, details);
4395 if (*extended_dictionary != *dictionary) {
4396 if (js_object->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS) {
4397 FixedArray::cast(js_object->elements())->set(1, *extended_dictionary);
4398 } else {
4399 js_object->set_elements(*extended_dictionary);
4400 }
4401 }
4402 return *obj_value;
4403 }
4404
4405 LookupResult result(isolate); 4358 LookupResult result(isolate);
4406 js_object->LocalLookupRealNamedProperty(*name, &result); 4359 js_object->LocalLookupRealNamedProperty(*name, &result);
4407 4360
4408 // Special case for callback properties. 4361 // Special case for callback properties.
4409 if (result.IsFound() && result.type() == CALLBACKS) { 4362 if (result.IsFound() && result.type() == CALLBACKS) {
4410 Object* callback = result.GetCallbackObject(); 4363 Object* callback = result.GetCallbackObject();
4411 // To be compatible with Safari we do not change the value on API objects 4364 // To be compatible with Safari we do not change the value on API objects
4412 // in Object.defineProperty(). Firefox disagrees here, and actually changes 4365 // in Object.defineProperty(). Firefox disagrees here, and actually changes
4413 // the value. 4366 // the value.
4414 if (callback->IsAccessorInfo()) { 4367 if (callback->IsAccessorInfo()) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
4450 } 4403 }
4451 4404
4452 return Runtime::ForceSetObjectProperty(isolate, 4405 return Runtime::ForceSetObjectProperty(isolate,
4453 js_object, 4406 js_object,
4454 name, 4407 name,
4455 obj_value, 4408 obj_value,
4456 attr); 4409 attr);
4457 } 4410 }
4458 4411
4459 4412
4460 // Special case for elements if any of the flags are true.
4461 // If elements are in fast case we always implicitly assume that:
4462 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false.
4463 static MaybeObject* NormalizeObjectSetElement(Isolate* isolate,
4464 Handle<JSObject> js_object,
4465 uint32_t index,
4466 Handle<Object> value,
4467 PropertyAttributes attr) {
4468 // Normalize the elements to enable attributes on the property.
4469 Handle<SeededNumberDictionary> dictionary =
4470 JSObject::NormalizeElements(js_object);
4471 // Make sure that we never go back to fast case.
4472 dictionary->set_requires_slow_elements();
4473 PropertyDetails details = PropertyDetails(attr, NORMAL);
4474 Handle<SeededNumberDictionary> extended_dictionary =
4475 SeededNumberDictionary::Set(dictionary, index, value, details);
4476 if (*extended_dictionary != *dictionary) {
4477 js_object->set_elements(*extended_dictionary);
4478 }
4479 return *value;
4480 }
4481
4482
4483 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, 4413 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
4484 Handle<Object> object, 4414 Handle<Object> object,
4485 Handle<Object> key, 4415 Handle<Object> key,
4486 Handle<Object> value, 4416 Handle<Object> value,
4487 PropertyAttributes attr, 4417 PropertyAttributes attr,
4488 StrictModeFlag strict_mode) { 4418 StrictModeFlag strict_mode) {
4419 SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
4489 HandleScope scope(isolate); 4420 HandleScope scope(isolate);
4490 4421
4491 if (object->IsUndefined() || object->IsNull()) { 4422 if (object->IsUndefined() || object->IsNull()) {
4492 Handle<Object> args[2] = { key, object }; 4423 Handle<Object> args[2] = { key, object };
4493 Handle<Object> error = 4424 Handle<Object> error =
4494 isolate->factory()->NewTypeError("non_object_property_store", 4425 isolate->factory()->NewTypeError("non_object_property_store",
4495 HandleVector(args, 2)); 4426 HandleVector(args, 2));
4496 return isolate->Throw(*error); 4427 return isolate->Throw(*error);
4497 } 4428 }
4498 4429
(...skipping 17 matching lines...) Expand all
4516 // of a string using [] notation. We need to support this too in 4447 // of a string using [] notation. We need to support this too in
4517 // JavaScript. 4448 // JavaScript.
4518 // In the case of a String object we just need to redirect the assignment to 4449 // In the case of a String object we just need to redirect the assignment to
4519 // the underlying string if the index is in range. Since the underlying 4450 // the underlying string if the index is in range. Since the underlying
4520 // string does nothing with the assignment then we can ignore such 4451 // string does nothing with the assignment then we can ignore such
4521 // assignments. 4452 // assignments.
4522 if (js_object->IsStringObjectWithCharacterAt(index)) { 4453 if (js_object->IsStringObjectWithCharacterAt(index)) {
4523 return *value; 4454 return *value;
4524 } 4455 }
4525 4456
4526 if (((attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0)) { 4457 Handle<Object> result = JSObject::SetElement(
4527 return NormalizeObjectSetElement(isolate, js_object, index, value, attr); 4458 js_object, index, value, attr, strict_mode, set_mode);
4528 }
4529
4530 Handle<Object> result =
4531 JSObject::SetElement(js_object, index, value, strict_mode);
4532 if (result.is_null()) return Failure::Exception(); 4459 if (result.is_null()) return Failure::Exception();
4533 return *value; 4460 return *value;
4534 } 4461 }
4535 4462
4536 if (key->IsString()) { 4463 if (key->IsString()) {
4537 Handle<Object> result; 4464 Handle<Object> result;
4538 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 4465 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4539 if (((attr & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0)) { 4466 result = JSObject::SetElement(
4540 return NormalizeObjectSetElement(isolate, 4467 js_object, index, value, attr, strict_mode, set_mode);
4541 js_object,
4542 index,
4543 value,
4544 attr);
4545 }
4546 result =
4547 JSObject::SetElement(js_object, index, value, strict_mode);
4548 } else { 4468 } else {
4549 Handle<String> key_string = Handle<String>::cast(key); 4469 Handle<String> key_string = Handle<String>::cast(key);
4550 key_string->TryFlatten(); 4470 key_string->TryFlatten();
4551 result = JSReceiver::SetProperty( 4471 result = JSReceiver::SetProperty(
4552 js_object, key_string, value, attr, strict_mode); 4472 js_object, key_string, value, attr, strict_mode);
4553 } 4473 }
4554 if (result.is_null()) return Failure::Exception(); 4474 if (result.is_null()) return Failure::Exception();
4555 return *value; 4475 return *value;
4556 } 4476 }
4557 4477
4558 // Call-back into JavaScript to convert the key to a string. 4478 // Call-back into JavaScript to convert the key to a string.
4559 bool has_pending_exception = false; 4479 bool has_pending_exception = false;
4560 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 4480 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4561 if (has_pending_exception) return Failure::Exception(); 4481 if (has_pending_exception) return Failure::Exception();
4562 Handle<String> name = Handle<String>::cast(converted); 4482 Handle<String> name = Handle<String>::cast(converted);
4563 4483
4564 if (name->AsArrayIndex(&index)) { 4484 if (name->AsArrayIndex(&index)) {
4565 return js_object->SetElement(index, *value, strict_mode, true); 4485 return js_object->SetElement(
4486 index, *value, attr, strict_mode, true, set_mode);
4566 } else { 4487 } else {
4567 return js_object->SetProperty(*name, *value, attr, strict_mode); 4488 return js_object->SetProperty(*name, *value, attr, strict_mode);
4568 } 4489 }
4569 } 4490 }
4570 4491
4571 4492
4572 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, 4493 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
4573 Handle<JSObject> js_object, 4494 Handle<JSObject> js_object,
4574 Handle<Object> key, 4495 Handle<Object> key,
4575 Handle<Object> value, 4496 Handle<Object> value,
4576 PropertyAttributes attr) { 4497 PropertyAttributes attr) {
4577 HandleScope scope(isolate); 4498 HandleScope scope(isolate);
4578 4499
4579 // Check if the given key is an array index. 4500 // Check if the given key is an array index.
4580 uint32_t index; 4501 uint32_t index;
4581 if (key->ToArrayIndex(&index)) { 4502 if (key->ToArrayIndex(&index)) {
4582 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters 4503 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4583 // of a string using [] notation. We need to support this too in 4504 // of a string using [] notation. We need to support this too in
4584 // JavaScript. 4505 // JavaScript.
4585 // In the case of a String object we just need to redirect the assignment to 4506 // In the case of a String object we just need to redirect the assignment to
4586 // the underlying string if the index is in range. Since the underlying 4507 // the underlying string if the index is in range. Since the underlying
4587 // string does nothing with the assignment then we can ignore such 4508 // string does nothing with the assignment then we can ignore such
4588 // assignments. 4509 // assignments.
4589 if (js_object->IsStringObjectWithCharacterAt(index)) { 4510 if (js_object->IsStringObjectWithCharacterAt(index)) {
4590 return *value; 4511 return *value;
4591 } 4512 }
4592 4513
4593 return js_object->SetElement(index, *value, kNonStrictMode, true); 4514 return js_object->SetElement(
4515 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4594 } 4516 }
4595 4517
4596 if (key->IsString()) { 4518 if (key->IsString()) {
4597 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 4519 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4598 return js_object->SetElement(index, *value, kNonStrictMode, true); 4520 return js_object->SetElement(
4521 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4599 } else { 4522 } else {
4600 Handle<String> key_string = Handle<String>::cast(key); 4523 Handle<String> key_string = Handle<String>::cast(key);
4601 key_string->TryFlatten(); 4524 key_string->TryFlatten();
4602 return js_object->SetLocalPropertyIgnoreAttributes(*key_string, 4525 return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
4603 *value, 4526 *value,
4604 attr); 4527 attr);
4605 } 4528 }
4606 } 4529 }
4607 4530
4608 // Call-back into JavaScript to convert the key to a string. 4531 // Call-back into JavaScript to convert the key to a string.
4609 bool has_pending_exception = false; 4532 bool has_pending_exception = false;
4610 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 4533 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4611 if (has_pending_exception) return Failure::Exception(); 4534 if (has_pending_exception) return Failure::Exception();
4612 Handle<String> name = Handle<String>::cast(converted); 4535 Handle<String> name = Handle<String>::cast(converted);
4613 4536
4614 if (name->AsArrayIndex(&index)) { 4537 if (name->AsArrayIndex(&index)) {
4615 return js_object->SetElement(index, *value, kNonStrictMode, true); 4538 return js_object->SetElement(
4539 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4616 } else { 4540 } else {
4617 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); 4541 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
4618 } 4542 }
4619 } 4543 }
4620 4544
4621 4545
4622 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate, 4546 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
4623 Handle<JSReceiver> receiver, 4547 Handle<JSReceiver> receiver,
4624 Handle<Object> key) { 4548 Handle<Object> key) {
4625 HandleScope scope(isolate); 4549 HandleScope scope(isolate);
(...skipping 5683 matching lines...) Expand 10 before | Expand all | Expand 10 after
10309 return isolate->ThrowIllegalOperation(); 10233 return isolate->ThrowIllegalOperation();
10310 } 10234 }
10311 10235
10312 Handle<JSObject> jsobject = Handle<JSObject>::cast(object); 10236 Handle<JSObject> jsobject = Handle<JSObject>::cast(object);
10313 Handle<Object> tmp1 = Object::GetElement(jsobject, index1); 10237 Handle<Object> tmp1 = Object::GetElement(jsobject, index1);
10314 RETURN_IF_EMPTY_HANDLE(isolate, tmp1); 10238 RETURN_IF_EMPTY_HANDLE(isolate, tmp1);
10315 Handle<Object> tmp2 = Object::GetElement(jsobject, index2); 10239 Handle<Object> tmp2 = Object::GetElement(jsobject, index2);
10316 RETURN_IF_EMPTY_HANDLE(isolate, tmp2); 10240 RETURN_IF_EMPTY_HANDLE(isolate, tmp2);
10317 10241
10318 RETURN_IF_EMPTY_HANDLE( 10242 RETURN_IF_EMPTY_HANDLE(
10319 isolate, JSObject::SetElement(jsobject, index1, tmp2, kStrictMode)); 10243 isolate, JSObject::SetElement(jsobject, index1, tmp2, NONE, kStrictMode));
10320 RETURN_IF_EMPTY_HANDLE( 10244 RETURN_IF_EMPTY_HANDLE(
10321 isolate, JSObject::SetElement(jsobject, index2, tmp1, kStrictMode)); 10245 isolate, JSObject::SetElement(jsobject, index2, tmp1, NONE, kStrictMode));
10322 10246
10323 return isolate->heap()->undefined_value(); 10247 return isolate->heap()->undefined_value();
10324 } 10248 }
10325 10249
10326 10250
10327 // Returns an array that tells you where in the [0, length) interval an array 10251 // Returns an array that tells you where in the [0, length) interval an array
10328 // might have elements. Can either return keys (positive integers) or 10252 // might have elements. Can either return keys (positive integers) or
10329 // intervals (pair of a negative integer (-start-1) followed by a 10253 // intervals (pair of a negative integer (-start-1) followed by a
10330 // positive (length)) or undefined values. 10254 // positive (length)) or undefined values.
10331 // Intervals can span over some keys that are not in the object. 10255 // Intervals can span over some keys that are not in the object.
(...skipping 3357 matching lines...) Expand 10 before | Expand all | Expand 10 after
13689 // Handle last resort GC and make sure to allow future allocations 13613 // Handle last resort GC and make sure to allow future allocations
13690 // to grow the heap without causing GCs (if possible). 13614 // to grow the heap without causing GCs (if possible).
13691 isolate->counters()->gc_last_resort_from_js()->Increment(); 13615 isolate->counters()->gc_last_resort_from_js()->Increment();
13692 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, 13616 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags,
13693 "Runtime::PerformGC"); 13617 "Runtime::PerformGC");
13694 } 13618 }
13695 } 13619 }
13696 13620
13697 13621
13698 } } // namespace v8::internal 13622 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/objects.cc ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698