Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 4344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4355 for (Object* current = this; | 4355 for (Object* current = this; |
| 4356 current != heap->null_value() && current->IsJSObject(); | 4356 current != heap->null_value() && current->IsJSObject(); |
| 4357 current = JSObject::cast(current)->GetPrototype()) { | 4357 current = JSObject::cast(current)->GetPrototype()) { |
| 4358 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 4358 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
| 4359 if (result->IsFound() && result->type() == CALLBACKS) return; | 4359 if (result->IsFound() && result->type() == CALLBACKS) return; |
| 4360 } | 4360 } |
| 4361 result->NotFound(); | 4361 result->NotFound(); |
| 4362 } | 4362 } |
| 4363 | 4363 |
| 4364 | 4364 |
| 4365 // Search for a getter or setter in an elements dictionary and update its | 4365 // Try to update an accessor in an elements dictionary. Return true if the |
| 4366 // attributes. Returns either undefined if the element is non-deletable, or the | 4366 // update succeeded, and false otherwise. |
| 4367 // getter/setter pair if there is an existing one, or the hole value if the | 4367 static bool UpdateGetterSetterInDictionary( |
| 4368 // element does not exist or is a normal non-getter/setter data element. | |
| 4369 static Object* UpdateGetterSetterInDictionary( | |
| 4370 SeededNumberDictionary* dictionary, | 4368 SeededNumberDictionary* dictionary, |
| 4371 uint32_t index, | 4369 uint32_t index, |
| 4372 PropertyAttributes attributes, | 4370 bool is_getter, |
| 4373 Heap* heap) { | 4371 Object* fun, |
| 4372 PropertyAttributes attributes) { | |
| 4374 int entry = dictionary->FindEntry(index); | 4373 int entry = dictionary->FindEntry(index); |
| 4375 if (entry != SeededNumberDictionary::kNotFound) { | 4374 if (entry != SeededNumberDictionary::kNotFound) { |
| 4376 Object* result = dictionary->ValueAt(entry); | 4375 Object* result = dictionary->ValueAt(entry); |
| 4377 PropertyDetails details = dictionary->DetailsAt(entry); | 4376 PropertyDetails details = dictionary->DetailsAt(entry); |
| 4378 // TODO(mstarzinger): We should check for details.IsDontDelete() here once | 4377 // TODO(mstarzinger): We should check for details.IsDontDelete() here once |
| 4379 // we only call into the runtime once to set both getter and setter. | 4378 // we only call into the runtime once to set both getter and setter. |
| 4380 if (details.type() == CALLBACKS && result->IsAccessorPair()) { | 4379 if (details.type() == CALLBACKS && result->IsAccessorPair()) { |
| 4381 if (details.attributes() != attributes) { | 4380 if (details.attributes() != attributes) { |
| 4382 dictionary->DetailsAtPut(entry, | 4381 dictionary->DetailsAtPut(entry, |
| 4383 PropertyDetails(attributes, CALLBACKS, index)); | 4382 PropertyDetails(attributes, CALLBACKS, index)); |
| 4384 } | 4383 } |
| 4385 return result; | 4384 AccessorPair::cast(result)->set(is_getter, fun); |
| 4385 return true; | |
| 4386 } | 4386 } |
| 4387 } | 4387 } |
| 4388 return heap->the_hole_value(); | 4388 return false; |
| 4389 } | 4389 } |
| 4390 | 4390 |
| 4391 | 4391 |
| 4392 MaybeObject* JSObject::DefineGetterSetter(String* name, | 4392 MaybeObject* JSObject::DefineElementAccessor(uint32_t index, |
| 4393 PropertyAttributes attributes) { | 4393 bool is_getter, |
| 4394 Heap* heap = GetHeap(); | 4394 Object* fun, |
| 4395 // Make sure that the top context does not change when doing callbacks or | 4395 PropertyAttributes attributes) { |
| 4396 // interceptor calls. | 4396 switch (GetElementsKind()) { |
| 4397 AssertNoContextChange ncc; | 4397 case FAST_SMI_ONLY_ELEMENTS: |
| 4398 | 4398 case FAST_ELEMENTS: |
| 4399 // Try to flatten before operating on the string. | 4399 case FAST_DOUBLE_ELEMENTS: |
| 4400 name->TryFlatten(); | 4400 break; |
| 4401 | 4401 case EXTERNAL_PIXEL_ELEMENTS: |
| 4402 if (!CanSetCallback(name)) { | 4402 case EXTERNAL_BYTE_ELEMENTS: |
| 4403 return heap->undefined_value(); | 4403 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4404 case EXTERNAL_SHORT_ELEMENTS: | |
| 4405 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | |
| 4406 case EXTERNAL_INT_ELEMENTS: | |
| 4407 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | |
| 4408 case EXTERNAL_FLOAT_ELEMENTS: | |
| 4409 case EXTERNAL_DOUBLE_ELEMENTS: | |
| 4410 // Ignore getters and setters on pixel and external array elements. | |
| 4411 return GetHeap()->undefined_value(); | |
| 4412 case DICTIONARY_ELEMENTS: | |
| 4413 if (UpdateGetterSetterInDictionary(element_dictionary(), | |
| 4414 index, | |
| 4415 is_getter, | |
| 4416 fun, | |
| 4417 attributes)) { | |
| 4418 return GetHeap()->undefined_value(); | |
|
Michael Starzinger
2012/02/22 10:24:38
I prefer having the result of GetHeap() in a local
Sven Panne
2012/02/22 10:52:18
I don't think that one possible additional memory
fschneider
2012/02/24 10:33:17
I don't buy the conciseness argument. heap->undefi
Sven Panne
2012/02/24 11:47:17
It's not about shorter lines, it's all about havin
Michael Starzinger
2012/02/24 12:44:09
Knowing that "heap" refers to the one and only hea
| |
| 4419 } | |
| 4420 break; | |
| 4421 case NON_STRICT_ARGUMENTS_ELEMENTS: { | |
| 4422 // Ascertain whether we have read-only properties or an existing | |
| 4423 // getter/setter pair in an arguments elements dictionary backing | |
| 4424 // store. | |
| 4425 FixedArray* parameter_map = FixedArray::cast(elements()); | |
| 4426 uint32_t length = parameter_map->length(); | |
| 4427 Object* probe = | |
| 4428 index < (length - 2) ? parameter_map->get(index + 2) : NULL; | |
| 4429 if (probe == NULL || probe->IsTheHole()) { | |
| 4430 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
| 4431 if (arguments->IsDictionary()) { | |
| 4432 SeededNumberDictionary* dictionary = | |
| 4433 SeededNumberDictionary::cast(arguments); | |
| 4434 if (UpdateGetterSetterInDictionary(dictionary, | |
| 4435 index, | |
| 4436 is_getter, | |
| 4437 fun, | |
| 4438 attributes)) { | |
| 4439 return GetHeap()->undefined_value(); | |
| 4440 } | |
| 4441 } | |
| 4442 } | |
| 4443 break; | |
| 4444 } | |
| 4404 } | 4445 } |
| 4405 | 4446 |
| 4406 uint32_t index = 0; | 4447 AccessorPair* accessors; |
| 4407 bool is_element = name->AsArrayIndex(&index); | 4448 { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair(); |
| 4449 if (!maybe_accessors->To(&accessors)) return maybe_accessors; | |
| 4450 } | |
| 4451 accessors->set(is_getter, fun); | |
| 4408 | 4452 |
| 4409 if (is_element) { | 4453 { MaybeObject* maybe_ok = SetElementCallback(index, accessors, attributes); |
|
Sven Panne
2012/02/24 11:47:17
I'll apply the same simplification here...
| |
| 4410 switch (GetElementsKind()) { | 4454 if (maybe_ok->IsFailure()) return maybe_ok; |
| 4411 case FAST_SMI_ONLY_ELEMENTS: | 4455 } |
| 4412 case FAST_ELEMENTS: | 4456 return GetHeap()->undefined_value(); |
| 4413 case FAST_DOUBLE_ELEMENTS: | 4457 } |
| 4414 break; | 4458 |
| 4415 case EXTERNAL_PIXEL_ELEMENTS: | 4459 |
| 4416 case EXTERNAL_BYTE_ELEMENTS: | 4460 MaybeObject* JSObject::DefinePropertyAccessor(String* name, |
| 4417 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4461 bool is_getter, |
| 4418 case EXTERNAL_SHORT_ELEMENTS: | 4462 Object* fun, |
| 4419 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4463 PropertyAttributes attributes) { |
| 4420 case EXTERNAL_INT_ELEMENTS: | 4464 // Lookup the name. |
| 4421 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4465 LookupResult result(GetHeap()->isolate()); |
| 4422 case EXTERNAL_FLOAT_ELEMENTS: | 4466 LocalLookupRealNamedProperty(name, &result); |
| 4423 case EXTERNAL_DOUBLE_ELEMENTS: | 4467 if (result.IsFound()) { |
| 4424 // Ignore getters and setters on pixel and external array | 4468 // TODO(mstarzinger): We should check for result.IsDontDelete() here once |
| 4425 // elements. | 4469 // we only call into the runtime once to set both getter and setter. |
| 4426 return heap->undefined_value(); | 4470 if (result.type() == CALLBACKS) { |
| 4427 case DICTIONARY_ELEMENTS: { | 4471 Object* obj = result.GetCallbackObject(); |
| 4428 Object* probe = UpdateGetterSetterInDictionary(element_dictionary(), | 4472 // Need to preserve old getters/setters. |
| 4429 index, | 4473 if (obj->IsAccessorPair()) { |
| 4430 attributes, | 4474 AccessorPair::cast(obj)->set(is_getter, fun); |
| 4431 heap); | 4475 // Use set to update attributes. |
| 4432 if (!probe->IsTheHole()) return probe; | 4476 { MaybeObject* maybe_ok = SetPropertyCallback(name, obj, attributes); |
| 4433 // Otherwise allow to override it. | 4477 if (maybe_ok->IsFailure()) return maybe_ok; |
| 4434 break; | |
| 4435 } | |
| 4436 case NON_STRICT_ARGUMENTS_ELEMENTS: { | |
| 4437 // Ascertain whether we have read-only properties or an existing | |
| 4438 // getter/setter pair in an arguments elements dictionary backing | |
| 4439 // store. | |
| 4440 FixedArray* parameter_map = FixedArray::cast(elements()); | |
| 4441 uint32_t length = parameter_map->length(); | |
| 4442 Object* probe = | |
| 4443 index < (length - 2) ? parameter_map->get(index + 2) : NULL; | |
| 4444 if (probe == NULL || probe->IsTheHole()) { | |
| 4445 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | |
| 4446 if (arguments->IsDictionary()) { | |
| 4447 SeededNumberDictionary* dictionary = | |
| 4448 SeededNumberDictionary::cast(arguments); | |
| 4449 probe = UpdateGetterSetterInDictionary(dictionary, | |
| 4450 index, | |
| 4451 attributes, | |
| 4452 heap); | |
| 4453 if (!probe->IsTheHole()) return probe; | |
| 4454 } | |
| 4455 } | 4478 } |
| 4456 break; | 4479 return GetHeap()->undefined_value(); |
|
fschneider
2012/02/24 10:33:17
return SetPropertyCallback(name, obj, attributes);
Sven Panne
2012/02/24 11:47:17
See remark below.
| |
| 4457 } | |
| 4458 } | |
| 4459 } else { | |
| 4460 // Lookup the name. | |
| 4461 LookupResult result(heap->isolate()); | |
| 4462 LocalLookupRealNamedProperty(name, &result); | |
| 4463 if (result.IsFound()) { | |
| 4464 // TODO(mstarzinger): We should check for result.IsDontDelete() here once | |
| 4465 // we only call into the runtime once to set both getter and setter. | |
| 4466 if (result.type() == CALLBACKS) { | |
| 4467 Object* obj = result.GetCallbackObject(); | |
| 4468 // Need to preserve old getters/setters. | |
| 4469 if (obj->IsAccessorPair()) { | |
| 4470 // Use set to update attributes. | |
| 4471 return SetPropertyCallback(name, obj, attributes); | |
| 4472 } | |
| 4473 } | 4480 } |
| 4474 } | 4481 } |
| 4475 } | 4482 } |
| 4476 | 4483 |
| 4477 AccessorPair* accessors; | 4484 AccessorPair* accessors; |
| 4478 { MaybeObject* maybe_accessors = heap->AllocateAccessorPair(); | 4485 { MaybeObject* maybe_accessors = GetHeap()->AllocateAccessorPair(); |
| 4479 if (!maybe_accessors->To<AccessorPair>(&accessors)) return maybe_accessors; | 4486 if (!maybe_accessors->To(&accessors)) return maybe_accessors; |
| 4480 } | 4487 } |
| 4488 accessors->set(is_getter, fun); | |
| 4481 | 4489 |
| 4482 if (is_element) { | 4490 { MaybeObject* maybe_ok = SetPropertyCallback(name, accessors, attributes); |
| 4483 return SetElementCallback(index, accessors, attributes); | 4491 if (maybe_ok->IsFailure()) return maybe_ok; |
| 4484 } else { | |
| 4485 return SetPropertyCallback(name, accessors, attributes); | |
| 4486 } | 4492 } |
| 4493 return GetHeap()->undefined_value(); | |
|
fschneider
2012/02/24 10:33:17
return SetPropertyCallback(name, accessors, attrib
Sven Panne
2012/02/24 11:47:17
Good point, I'll submit a separate CL for this min
| |
| 4487 } | 4494 } |
| 4488 | 4495 |
| 4489 | 4496 |
| 4490 bool JSObject::CanSetCallback(String* name) { | 4497 bool JSObject::CanSetCallback(String* name) { |
| 4491 ASSERT(!IsAccessCheckNeeded() || | 4498 ASSERT(!IsAccessCheckNeeded() || |
| 4492 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 4499 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
| 4493 | 4500 |
| 4494 // Check if there is an API defined callback object which prohibits | 4501 // Check if there is an API defined callback object which prohibits |
| 4495 // callback overwriting in this object or it's prototype chain. | 4502 // callback overwriting in this object or it's prototype chain. |
| 4496 // This mechanism is needed for instance in a browser setting, where | 4503 // This mechanism is needed for instance in a browser setting, where |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 4510 return true; | 4517 return true; |
| 4511 } | 4518 } |
| 4512 | 4519 |
| 4513 | 4520 |
| 4514 MaybeObject* JSObject::SetElementCallback(uint32_t index, | 4521 MaybeObject* JSObject::SetElementCallback(uint32_t index, |
| 4515 Object* structure, | 4522 Object* structure, |
| 4516 PropertyAttributes attributes) { | 4523 PropertyAttributes attributes) { |
| 4517 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); | 4524 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); |
| 4518 | 4525 |
| 4519 // Normalize elements to make this operation simple. | 4526 // Normalize elements to make this operation simple. |
| 4520 SeededNumberDictionary* dictionary = NULL; | 4527 SeededNumberDictionary* dictionary; |
| 4521 { Object* result; | 4528 { MaybeObject* maybe_dictionary = NormalizeElements(); |
| 4522 MaybeObject* maybe = NormalizeElements(); | 4529 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
| 4523 if (!maybe->ToObject(&result)) return maybe; | |
| 4524 dictionary = SeededNumberDictionary::cast(result); | |
| 4525 } | 4530 } |
| 4526 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 4531 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
| 4527 | 4532 |
| 4528 // Update the dictionary with the new CALLBACKS property. | 4533 // Update the dictionary with the new CALLBACKS property. |
| 4529 { Object* result; | 4534 { MaybeObject* maybe_dictionary = dictionary->Set(index, structure, details); |
| 4530 MaybeObject* maybe = dictionary->Set(index, structure, details); | 4535 if (!maybe_dictionary->To(&dictionary)) return maybe_dictionary; |
| 4531 if (!maybe->ToObject(&result)) return maybe; | |
| 4532 dictionary = SeededNumberDictionary::cast(result); | |
| 4533 } | 4536 } |
| 4534 | 4537 |
| 4535 dictionary->set_requires_slow_elements(); | 4538 dictionary->set_requires_slow_elements(); |
| 4536 // Update the dictionary backing store on the object. | 4539 // Update the dictionary backing store on the object. |
| 4537 if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) { | 4540 if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) { |
| 4538 // Also delete any parameter alias. | 4541 // Also delete any parameter alias. |
| 4539 // | 4542 // |
| 4540 // TODO(kmillikin): when deleting the last parameter alias we could | 4543 // TODO(kmillikin): when deleting the last parameter alias we could |
| 4541 // switch to a direct backing store without the parameter map. This | 4544 // switch to a direct backing store without the parameter map. This |
| 4542 // would allow GC of the context. | 4545 // would allow GC of the context. |
| 4543 FixedArray* parameter_map = FixedArray::cast(elements()); | 4546 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 4544 uint32_t length = parameter_map->length(); | 4547 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { |
| 4545 if (index < length - 2) { | |
| 4546 parameter_map->set(index + 2, GetHeap()->the_hole_value()); | 4548 parameter_map->set(index + 2, GetHeap()->the_hole_value()); |
| 4547 } | 4549 } |
| 4548 parameter_map->set(1, dictionary); | 4550 parameter_map->set(1, dictionary); |
| 4549 } else { | 4551 } else { |
| 4550 set_elements(dictionary); | 4552 set_elements(dictionary); |
| 4551 } | 4553 } |
| 4552 | 4554 |
| 4553 return structure; | 4555 return GetHeap()->undefined_value(); |
| 4554 } | 4556 } |
| 4555 | 4557 |
| 4556 | 4558 |
| 4557 MaybeObject* JSObject::SetPropertyCallback(String* name, | 4559 MaybeObject* JSObject::SetPropertyCallback(String* name, |
| 4558 Object* structure, | 4560 Object* structure, |
| 4559 PropertyAttributes attributes) { | 4561 PropertyAttributes attributes) { |
| 4560 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); | 4562 PropertyDetails details = PropertyDetails(attributes, CALLBACKS); |
| 4561 | 4563 |
| 4562 bool convert_back_to_fast = HasFastProperties() && | 4564 bool convert_back_to_fast = HasFastProperties() && |
| 4563 (map()->instance_descriptors()->number_of_descriptors() | 4565 (map()->instance_descriptors()->number_of_descriptors() |
| 4564 < DescriptorArray::kMaxNumberOfDescriptors); | 4566 < DescriptorArray::kMaxNumberOfDescriptors); |
| 4565 | 4567 |
| 4566 // Normalize object to make this operation simple. | 4568 // Normalize object to make this operation simple. |
| 4567 Object* ok; | |
| 4568 { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 4569 { MaybeObject* maybe_ok = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 4569 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 4570 if (maybe_ok->IsFailure()) return maybe_ok; |
| 4570 } | 4571 } |
| 4571 | 4572 |
| 4572 // For the global object allocate a new map to invalidate the global inline | 4573 // For the global object allocate a new map to invalidate the global inline |
| 4573 // caches which have a global property cell reference directly in the code. | 4574 // caches which have a global property cell reference directly in the code. |
| 4574 if (IsGlobalObject()) { | 4575 if (IsGlobalObject()) { |
| 4575 Object* new_map; | 4576 Map* new_map; |
| 4576 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); | 4577 { MaybeObject* maybe_new_map = map()->CopyDropDescriptors(); |
| 4577 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 4578 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 4578 } | 4579 } |
| 4579 set_map(Map::cast(new_map)); | 4580 set_map(new_map); |
| 4580 // When running crankshaft, changing the map is not enough. We | 4581 // When running crankshaft, changing the map is not enough. We |
| 4581 // need to deoptimize all functions that rely on this global | 4582 // need to deoptimize all functions that rely on this global |
| 4582 // object. | 4583 // object. |
| 4583 Deoptimizer::DeoptimizeGlobalObject(this); | 4584 Deoptimizer::DeoptimizeGlobalObject(this); |
| 4584 } | 4585 } |
| 4585 | 4586 |
| 4586 // Update the dictionary with the new CALLBACKS property. | 4587 // Update the dictionary with the new CALLBACKS property. |
| 4587 Object* result; | 4588 { MaybeObject* maybe_ok = SetNormalizedProperty(name, structure, details); |
| 4588 { MaybeObject* maybe_result = SetNormalizedProperty(name, structure, details); | 4589 if (maybe_ok->IsFailure()) return maybe_ok; |
| 4589 if (!maybe_result->ToObject(&result)) return maybe_result; | |
| 4590 } | 4590 } |
| 4591 | 4591 |
| 4592 if (convert_back_to_fast) { | 4592 if (convert_back_to_fast) { |
| 4593 { MaybeObject* maybe_ok = TransformToFastProperties(0); | 4593 MaybeObject* maybe_ok = TransformToFastProperties(0); |
| 4594 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 4594 if (maybe_ok->IsFailure()) return maybe_ok; |
| 4595 } | |
| 4596 } | 4595 } |
| 4597 return result; | 4596 return GetHeap()->undefined_value(); |
| 4598 } | 4597 } |
| 4599 | 4598 |
| 4600 MaybeObject* JSObject::DefineAccessor(String* name, | 4599 MaybeObject* JSObject::DefineAccessor(String* name, |
| 4601 bool is_getter, | 4600 bool is_getter, |
| 4602 Object* fun, | 4601 Object* fun, |
| 4603 PropertyAttributes attributes) { | 4602 PropertyAttributes attributes) { |
| 4604 ASSERT(fun->IsSpecFunction() || fun->IsUndefined()); | 4603 ASSERT(fun->IsSpecFunction() || fun->IsUndefined()); |
| 4605 Isolate* isolate = GetIsolate(); | 4604 Isolate* isolate = GetIsolate(); |
| 4606 // Check access rights if needed. | 4605 // Check access rights if needed. |
| 4607 if (IsAccessCheckNeeded() && | 4606 if (IsAccessCheckNeeded() && |
| 4608 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 4607 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 4609 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 4608 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 4610 return isolate->heap()->undefined_value(); | 4609 return isolate->heap()->undefined_value(); |
| 4611 } | 4610 } |
| 4612 | 4611 |
| 4613 if (IsJSGlobalProxy()) { | 4612 if (IsJSGlobalProxy()) { |
| 4614 Object* proto = GetPrototype(); | 4613 Object* proto = GetPrototype(); |
| 4615 if (proto->IsNull()) return this; | 4614 if (proto->IsNull()) return this; |
| 4616 ASSERT(proto->IsJSGlobalObject()); | 4615 ASSERT(proto->IsJSGlobalObject()); |
| 4617 return JSObject::cast(proto)->DefineAccessor(name, is_getter, | 4616 return JSObject::cast(proto)->DefineAccessor(name, is_getter, |
| 4618 fun, attributes); | 4617 fun, attributes); |
| 4619 } | 4618 } |
| 4620 | 4619 |
| 4621 Object* accessors; | 4620 // Make sure that the top context does not change when doing callbacks or |
| 4622 { MaybeObject* maybe_accessors = DefineGetterSetter(name, attributes); | 4621 // interceptor calls. |
| 4623 if (!maybe_accessors->To<Object>(&accessors)) return maybe_accessors; | 4622 AssertNoContextChange ncc; |
| 4624 } | 4623 |
| 4625 if (accessors->IsUndefined()) return accessors; | 4624 // Try to flatten before operating on the string. |
| 4626 if (is_getter) { | 4625 name->TryFlatten(); |
| 4627 AccessorPair::cast(accessors)->set_getter(fun); | 4626 |
| 4628 } else { | 4627 if (!CanSetCallback(name)) return isolate->heap()->undefined_value(); |
| 4629 AccessorPair::cast(accessors)->set_setter(fun); | 4628 |
| 4630 } | 4629 uint32_t index = 0; |
| 4631 return this; | 4630 return name->AsArrayIndex(&index) ? |
| 4631 DefineElementAccessor(index, is_getter, fun, attributes) : | |
| 4632 DefinePropertyAccessor(name, is_getter, fun, attributes); | |
| 4632 } | 4633 } |
| 4633 | 4634 |
| 4634 | 4635 |
| 4635 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { | 4636 MaybeObject* JSObject::DefineAccessor(AccessorInfo* info) { |
| 4636 Isolate* isolate = GetIsolate(); | 4637 Isolate* isolate = GetIsolate(); |
| 4637 String* name = String::cast(info->name()); | 4638 String* name = String::cast(info->name()); |
| 4638 // Check access rights if needed. | 4639 // Check access rights if needed. |
| 4639 if (IsAccessCheckNeeded() && | 4640 if (IsAccessCheckNeeded() && |
| 4640 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 4641 !isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 4641 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 4642 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4684 // Ignore getters and setters on pixel and external array | 4685 // Ignore getters and setters on pixel and external array |
| 4685 // elements. | 4686 // elements. |
| 4686 return isolate->heap()->undefined_value(); | 4687 return isolate->heap()->undefined_value(); |
| 4687 case DICTIONARY_ELEMENTS: | 4688 case DICTIONARY_ELEMENTS: |
| 4688 break; | 4689 break; |
| 4689 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4690 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 4690 UNIMPLEMENTED(); | 4691 UNIMPLEMENTED(); |
| 4691 break; | 4692 break; |
| 4692 } | 4693 } |
| 4693 | 4694 |
| 4694 Object* ok; | |
| 4695 { MaybeObject* maybe_ok = | 4695 { MaybeObject* maybe_ok = |
| 4696 SetElementCallback(index, info, info->property_attributes()); | 4696 SetElementCallback(index, info, info->property_attributes()); |
| 4697 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 4697 if (maybe_ok->IsFailure()) return maybe_ok; |
| 4698 } | 4698 } |
| 4699 } else { | 4699 } else { |
| 4700 // Lookup the name. | 4700 // Lookup the name. |
| 4701 LookupResult result(isolate); | 4701 LookupResult result(isolate); |
| 4702 LocalLookup(name, &result); | 4702 LocalLookup(name, &result); |
| 4703 // ES5 forbids turning a property into an accessor if it's not | 4703 // ES5 forbids turning a property into an accessor if it's not |
| 4704 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). | 4704 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). |
| 4705 if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { | 4705 if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { |
| 4706 return isolate->heap()->undefined_value(); | 4706 return isolate->heap()->undefined_value(); |
| 4707 } | 4707 } |
| 4708 Object* ok; | |
| 4709 { MaybeObject* maybe_ok = | 4708 { MaybeObject* maybe_ok = |
| 4710 SetPropertyCallback(name, info, info->property_attributes()); | 4709 SetPropertyCallback(name, info, info->property_attributes()); |
| 4711 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 4710 if (maybe_ok->IsFailure()) return maybe_ok; |
| 4712 } | 4711 } |
| 4713 } | 4712 } |
| 4714 | 4713 |
| 4715 return this; | 4714 return this; |
| 4716 } | 4715 } |
| 4717 | 4716 |
| 4718 | 4717 |
| 4719 Object* JSObject::LookupAccessor(String* name, bool is_getter) { | 4718 Object* JSObject::LookupAccessor(String* name, bool is_getter) { |
| 4720 Heap* heap = GetHeap(); | 4719 Heap* heap = GetHeap(); |
| 4721 | 4720 |
| (...skipping 7943 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12665 } else { | 12664 } else { |
| 12666 int offset = current_offset - inobject_props; | 12665 int offset = current_offset - inobject_props; |
| 12667 FixedArray::cast(fields)->set(offset, value); | 12666 FixedArray::cast(fields)->set(offset, value); |
| 12668 } | 12667 } |
| 12669 FieldDescriptor d(String::cast(key), | 12668 FieldDescriptor d(String::cast(key), |
| 12670 current_offset++, | 12669 current_offset++, |
| 12671 details.attributes(), | 12670 details.attributes(), |
| 12672 details.index()); | 12671 details.index()); |
| 12673 descriptors->Set(next_descriptor++, &d, witness); | 12672 descriptors->Set(next_descriptor++, &d, witness); |
| 12674 } else if (type == CALLBACKS) { | 12673 } else if (type == CALLBACKS) { |
| 12674 if (value->IsAccessorPair()) { | |
| 12675 MaybeObject* maybe_copy = | |
| 12676 AccessorPair::cast(value)->CopyWithoutTransitions(); | |
| 12677 if (!maybe_copy->To(&value)) return maybe_copy; | |
| 12678 } | |
| 12675 CallbacksDescriptor d(String::cast(key), | 12679 CallbacksDescriptor d(String::cast(key), |
| 12676 value, | 12680 value, |
| 12677 details.attributes(), | 12681 details.attributes(), |
| 12678 details.index()); | 12682 details.index()); |
| 12679 descriptors->Set(next_descriptor++, &d, witness); | 12683 descriptors->Set(next_descriptor++, &d, witness); |
| 12680 } else { | 12684 } else { |
| 12681 UNREACHABLE(); | 12685 UNREACHABLE(); |
| 12682 } | 12686 } |
| 12683 } | 12687 } |
| 12684 } | 12688 } |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13075 if (break_point_objects()->IsUndefined()) return 0; | 13079 if (break_point_objects()->IsUndefined()) return 0; |
| 13076 // Single break point. | 13080 // Single break point. |
| 13077 if (!break_point_objects()->IsFixedArray()) return 1; | 13081 if (!break_point_objects()->IsFixedArray()) return 1; |
| 13078 // Multiple break points. | 13082 // Multiple break points. |
| 13079 return FixedArray::cast(break_point_objects())->length(); | 13083 return FixedArray::cast(break_point_objects())->length(); |
| 13080 } | 13084 } |
| 13081 #endif // ENABLE_DEBUGGER_SUPPORT | 13085 #endif // ENABLE_DEBUGGER_SUPPORT |
| 13082 | 13086 |
| 13083 | 13087 |
| 13084 } } // namespace v8::internal | 13088 } } // namespace v8::internal |
| OLD | NEW |