| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 #include "vm-state-inl.h" | 48 #include "vm-state-inl.h" |
| 49 | 49 |
| 50 #ifdef ENABLE_DISASSEMBLER | 50 #ifdef ENABLE_DISASSEMBLER |
| 51 #include "disasm.h" | 51 #include "disasm.h" |
| 52 #include "disassembler.h" | 52 #include "disassembler.h" |
| 53 #endif | 53 #endif |
| 54 | 54 |
| 55 namespace v8 { | 55 namespace v8 { |
| 56 namespace internal { | 56 namespace internal { |
| 57 | 57 |
| 58 void PrintElementsKind(FILE* out, ElementsKind kind) { |
| 59 switch (kind) { |
| 60 case FAST_SMI_ONLY_ELEMENTS: |
| 61 PrintF(out, "FAST_SMI_ONLY_ELEMENTS"); |
| 62 break; |
| 63 case FAST_ELEMENTS: |
| 64 PrintF(out, "FAST_ELEMENTS"); |
| 65 break; |
| 66 case FAST_DOUBLE_ELEMENTS: |
| 67 PrintF(out, "FAST_DOUBLE_ELEMENTS"); |
| 68 break; |
| 69 case DICTIONARY_ELEMENTS: |
| 70 PrintF(out, "DICTIONARY_ELEMENTS"); |
| 71 break; |
| 72 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 73 PrintF(out, "NON_STRICT_ARGUMENTS_ELEMENTS"); |
| 74 break; |
| 75 case EXTERNAL_BYTE_ELEMENTS: |
| 76 PrintF(out, "EXTERNAL_BYTE_ELEMENTS"); |
| 77 break; |
| 78 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 79 PrintF(out, "EXTERNAL_UNSIGNED_BYTE_ELEMENTS"); |
| 80 break; |
| 81 case EXTERNAL_SHORT_ELEMENTS: |
| 82 PrintF(out, "EXTERNAL_SHORT_ELEMENTS"); |
| 83 break; |
| 84 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 85 PrintF(out, "EXTERNAL_UNSIGNED_SHORT_ELEMENTS"); |
| 86 break; |
| 87 case EXTERNAL_INT_ELEMENTS: |
| 88 PrintF(out, "EXTERNAL_INT_ELEMENTS"); |
| 89 break; |
| 90 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 91 PrintF(out, "EXTERNAL_UNSIGNED_INT_ELEMENTS"); |
| 92 break; |
| 93 case EXTERNAL_FLOAT_ELEMENTS: |
| 94 PrintF(out, "EXTERNAL_FLOAT_ELEMENTS"); |
| 95 break; |
| 96 case EXTERNAL_DOUBLE_ELEMENTS: |
| 97 PrintF(out, "EXTERNAL_DOUBLE_ELEMENTS"); |
| 98 break; |
| 99 case EXTERNAL_PIXEL_ELEMENTS: |
| 100 PrintF(out, "EXTERNAL_DOUBLE_ELEMENTS"); |
| 101 break; |
| 102 } |
| 103 } |
| 104 |
| 105 |
| 58 // Getters and setters are stored in a fixed array property. These are | 106 // Getters and setters are stored in a fixed array property. These are |
| 59 // constants for their indices. | 107 // constants for their indices. |
| 60 const int kGetterIndex = 0; | 108 const int kGetterIndex = 0; |
| 61 const int kSetterIndex = 1; | 109 const int kSetterIndex = 1; |
| 62 | 110 |
| 63 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, | 111 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, |
| 64 Object* value) { | 112 Object* value) { |
| 65 Object* result; | 113 Object* result; |
| 66 { MaybeObject* maybe_result = | 114 { MaybeObject* maybe_result = |
| 67 constructor->GetHeap()->AllocateJSObject(constructor); | 115 constructor->GetHeap()->AllocateJSObject(constructor); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 } | 195 } |
| 148 } | 196 } |
| 149 ASSERT(holder != NULL); // Cannot handle null or undefined. | 197 ASSERT(holder != NULL); // Cannot handle null or undefined. |
| 150 JSReceiver::cast(holder)->Lookup(name, result); | 198 JSReceiver::cast(holder)->Lookup(name, result); |
| 151 } | 199 } |
| 152 | 200 |
| 153 | 201 |
| 154 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, | 202 MaybeObject* Object::GetPropertyWithReceiver(Object* receiver, |
| 155 String* name, | 203 String* name, |
| 156 PropertyAttributes* attributes) { | 204 PropertyAttributes* attributes) { |
| 157 LookupResult result; | 205 LookupResult result(name->GetIsolate()); |
| 158 Lookup(name, &result); | 206 Lookup(name, &result); |
| 159 MaybeObject* value = GetProperty(receiver, &result, name, attributes); | 207 MaybeObject* value = GetProperty(receiver, &result, name, attributes); |
| 160 ASSERT(*attributes <= ABSENT); | 208 ASSERT(*attributes <= ABSENT); |
| 161 return value; | 209 return value; |
| 162 } | 210 } |
| 163 | 211 |
| 164 | 212 |
| 165 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver, | 213 MaybeObject* JSObject::GetPropertyWithCallback(Object* receiver, |
| 166 Object* structure, | 214 Object* structure, |
| 167 String* name) { | 215 String* name) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 | 275 |
| 228 Handle<Object> args[] = { receiver, name }; | 276 Handle<Object> args[] = { receiver, name }; |
| 229 Handle<Object> result = CallTrap( | 277 Handle<Object> result = CallTrap( |
| 230 "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args); | 278 "get", isolate->derived_get_trap(), ARRAY_SIZE(args), args); |
| 231 if (isolate->has_pending_exception()) return Failure::Exception(); | 279 if (isolate->has_pending_exception()) return Failure::Exception(); |
| 232 | 280 |
| 233 return *result; | 281 return *result; |
| 234 } | 282 } |
| 235 | 283 |
| 236 | 284 |
| 285 Handle<Object> Object::GetElement(Handle<Object> object, uint32_t index) { |
| 286 Isolate* isolate = object->IsHeapObject() |
| 287 ? Handle<HeapObject>::cast(object)->GetIsolate() |
| 288 : Isolate::Current(); |
| 289 CALL_HEAP_FUNCTION(isolate, object->GetElement(index), Object); |
| 290 } |
| 291 |
| 292 |
| 237 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver, | 293 MaybeObject* JSProxy::GetElementWithHandler(Object* receiver, |
| 238 uint32_t index) { | 294 uint32_t index) { |
| 239 String* name; | 295 String* name; |
| 240 MaybeObject* maybe = GetHeap()->Uint32ToString(index); | 296 MaybeObject* maybe = GetHeap()->Uint32ToString(index); |
| 241 if (!maybe->To<String>(&name)) return maybe; | 297 if (!maybe->To<String>(&name)) return maybe; |
| 242 return GetPropertyWithHandler(receiver, name); | 298 return GetPropertyWithHandler(receiver, name); |
| 243 } | 299 } |
| 244 | 300 |
| 245 | 301 |
| 246 MaybeObject* JSProxy::SetElementWithHandler(uint32_t index, | 302 MaybeObject* JSProxy::SetElementWithHandler(uint32_t index, |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 return result->holder()->GetPropertyWithCallback( | 359 return result->holder()->GetPropertyWithCallback( |
| 304 receiver, result->GetCallbackObject(), name); | 360 receiver, result->GetCallbackObject(), name); |
| 305 } | 361 } |
| 306 } | 362 } |
| 307 break; | 363 break; |
| 308 } | 364 } |
| 309 case NORMAL: | 365 case NORMAL: |
| 310 case FIELD: | 366 case FIELD: |
| 311 case CONSTANT_FUNCTION: { | 367 case CONSTANT_FUNCTION: { |
| 312 // Search ALL_CAN_READ accessors in prototype chain. | 368 // Search ALL_CAN_READ accessors in prototype chain. |
| 313 LookupResult r; | 369 LookupResult r(GetIsolate()); |
| 314 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | 370 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); |
| 315 if (r.IsProperty()) { | 371 if (r.IsProperty()) { |
| 316 return GetPropertyWithFailedAccessCheck(receiver, | 372 return GetPropertyWithFailedAccessCheck(receiver, |
| 317 &r, | 373 &r, |
| 318 name, | 374 name, |
| 319 attributes); | 375 attributes); |
| 320 } | 376 } |
| 321 break; | 377 break; |
| 322 } | 378 } |
| 323 case INTERCEPTOR: { | 379 case INTERCEPTOR: { |
| 324 // If the object has an interceptor, try real named properties. | 380 // If the object has an interceptor, try real named properties. |
| 325 // No access check in GetPropertyAttributeWithInterceptor. | 381 // No access check in GetPropertyAttributeWithInterceptor. |
| 326 LookupResult r; | 382 LookupResult r(GetIsolate()); |
| 327 result->holder()->LookupRealNamedProperty(name, &r); | 383 result->holder()->LookupRealNamedProperty(name, &r); |
| 328 if (r.IsProperty()) { | 384 if (r.IsProperty()) { |
| 329 return GetPropertyWithFailedAccessCheck(receiver, | 385 return GetPropertyWithFailedAccessCheck(receiver, |
| 330 &r, | 386 &r, |
| 331 name, | 387 name, |
| 332 attributes); | 388 attributes); |
| 333 } | 389 } |
| 334 break; | 390 break; |
| 335 } | 391 } |
| 336 default: | 392 default: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 363 } | 419 } |
| 364 } | 420 } |
| 365 break; | 421 break; |
| 366 } | 422 } |
| 367 | 423 |
| 368 case NORMAL: | 424 case NORMAL: |
| 369 case FIELD: | 425 case FIELD: |
| 370 case CONSTANT_FUNCTION: { | 426 case CONSTANT_FUNCTION: { |
| 371 if (!continue_search) break; | 427 if (!continue_search) break; |
| 372 // Search ALL_CAN_READ accessors in prototype chain. | 428 // Search ALL_CAN_READ accessors in prototype chain. |
| 373 LookupResult r; | 429 LookupResult r(GetIsolate()); |
| 374 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | 430 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); |
| 375 if (r.IsProperty()) { | 431 if (r.IsProperty()) { |
| 376 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 432 return GetPropertyAttributeWithFailedAccessCheck(receiver, |
| 377 &r, | 433 &r, |
| 378 name, | 434 name, |
| 379 continue_search); | 435 continue_search); |
| 380 } | 436 } |
| 381 break; | 437 break; |
| 382 } | 438 } |
| 383 | 439 |
| 384 case INTERCEPTOR: { | 440 case INTERCEPTOR: { |
| 385 // If the object has an interceptor, try real named properties. | 441 // If the object has an interceptor, try real named properties. |
| 386 // No access check in GetPropertyAttributeWithInterceptor. | 442 // No access check in GetPropertyAttributeWithInterceptor. |
| 387 LookupResult r; | 443 LookupResult r(GetIsolate()); |
| 388 if (continue_search) { | 444 if (continue_search) { |
| 389 result->holder()->LookupRealNamedProperty(name, &r); | 445 result->holder()->LookupRealNamedProperty(name, &r); |
| 390 } else { | 446 } else { |
| 391 result->holder()->LocalLookupRealNamedProperty(name, &r); | 447 result->holder()->LocalLookupRealNamedProperty(name, &r); |
| 392 } | 448 } |
| 393 if (r.IsProperty()) { | 449 if (r.IsProperty()) { |
| 394 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 450 return GetPropertyAttributeWithFailedAccessCheck(receiver, |
| 395 &r, | 451 &r, |
| 396 name, | 452 name, |
| 397 continue_search); | 453 continue_search); |
| 398 } | 454 } |
| 399 break; | 455 break; |
| 400 } | 456 } |
| 401 | 457 |
| 402 default: | 458 default: |
| 403 UNREACHABLE(); | 459 UNREACHABLE(); |
| 404 } | 460 } |
| 405 } | 461 } |
| 406 | 462 |
| 407 GetHeap()->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 463 GetIsolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 408 return ABSENT; | 464 return ABSENT; |
| 409 } | 465 } |
| 410 | 466 |
| 411 | 467 |
| 412 Object* JSObject::GetNormalizedProperty(LookupResult* result) { | 468 Object* JSObject::GetNormalizedProperty(LookupResult* result) { |
| 413 ASSERT(!HasFastProperties()); | 469 ASSERT(!HasFastProperties()); |
| 414 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 470 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 415 if (IsGlobalObject()) { | 471 if (IsGlobalObject()) { |
| 416 value = JSGlobalPropertyCell::cast(value)->value(); | 472 value = JSGlobalPropertyCell::cast(value)->value(); |
| 417 } | 473 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 if (!fun->shared()->IsApiFunction()) | 577 if (!fun->shared()->IsApiFunction()) |
| 522 return true; | 578 return true; |
| 523 // If the object is fully fast case and has the same map it was | 579 // If the object is fully fast case and has the same map it was |
| 524 // created with then no changes can have been made to it. | 580 // created with then no changes can have been made to it. |
| 525 return map() != fun->initial_map() | 581 return map() != fun->initial_map() |
| 526 || !HasFastElements() | 582 || !HasFastElements() |
| 527 || !HasFastProperties(); | 583 || !HasFastProperties(); |
| 528 } | 584 } |
| 529 | 585 |
| 530 | 586 |
| 587 Handle<Object> Object::GetProperty(Handle<Object> object, |
| 588 Handle<Object> receiver, |
| 589 LookupResult* result, |
| 590 Handle<String> key, |
| 591 PropertyAttributes* attributes) { |
| 592 Isolate* isolate = object->IsHeapObject() |
| 593 ? Handle<HeapObject>::cast(object)->GetIsolate() |
| 594 : Isolate::Current(); |
| 595 CALL_HEAP_FUNCTION( |
| 596 isolate, |
| 597 object->GetProperty(*receiver, result, *key, attributes), |
| 598 Object); |
| 599 } |
| 600 |
| 601 |
| 531 MaybeObject* Object::GetProperty(Object* receiver, | 602 MaybeObject* Object::GetProperty(Object* receiver, |
| 532 LookupResult* result, | 603 LookupResult* result, |
| 533 String* name, | 604 String* name, |
| 534 PropertyAttributes* attributes) { | 605 PropertyAttributes* attributes) { |
| 535 // Make sure that the top context does not change when doing | 606 // Make sure that the top context does not change when doing |
| 536 // callbacks or interceptor calls. | 607 // callbacks or interceptor calls. |
| 537 AssertNoContextChange ncc; | 608 AssertNoContextChange ncc; |
| 538 Heap* heap = name->GetHeap(); | 609 Heap* heap = name->GetHeap(); |
| 539 | 610 |
| 540 // Traverse the prototype chain from the current object (this) to | 611 // Traverse the prototype chain from the current object (this) to |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 return context->string_function()->instance_prototype(); | 764 return context->string_function()->instance_prototype(); |
| 694 } | 765 } |
| 695 if (heap_object->IsBoolean()) { | 766 if (heap_object->IsBoolean()) { |
| 696 return context->boolean_function()->instance_prototype(); | 767 return context->boolean_function()->instance_prototype(); |
| 697 } else { | 768 } else { |
| 698 return heap->null_value(); | 769 return heap->null_value(); |
| 699 } | 770 } |
| 700 } | 771 } |
| 701 | 772 |
| 702 | 773 |
| 774 MaybeObject* Object::GetHash(CreationFlag flag) { |
| 775 // The object is either a number, a string, an odd-ball, |
| 776 // a real JS object, or a Harmony proxy. |
| 777 if (IsNumber()) { |
| 778 uint32_t hash = ComputeLongHash(double_to_uint64(Number())); |
| 779 return Smi::FromInt(hash & Smi::kMaxValue); |
| 780 } |
| 781 if (IsString()) { |
| 782 uint32_t hash = String::cast(this)->Hash(); |
| 783 return Smi::FromInt(hash); |
| 784 } |
| 785 if (IsOddball()) { |
| 786 uint32_t hash = Oddball::cast(this)->to_string()->Hash(); |
| 787 return Smi::FromInt(hash); |
| 788 } |
| 789 if (IsJSReceiver()) { |
| 790 return JSReceiver::cast(this)->GetIdentityHash(flag); |
| 791 } |
| 792 |
| 793 UNREACHABLE(); |
| 794 return Smi::FromInt(0); |
| 795 } |
| 796 |
| 797 |
| 798 bool Object::SameValue(Object* other) { |
| 799 if (other == this) return true; |
| 800 if (!IsHeapObject() || !other->IsHeapObject()) return false; |
| 801 |
| 802 // The object is either a number, a string, an odd-ball, |
| 803 // a real JS object, or a Harmony proxy. |
| 804 if (IsNumber() && other->IsNumber()) { |
| 805 double this_value = Number(); |
| 806 double other_value = other->Number(); |
| 807 return (this_value == other_value) || |
| 808 (isnan(this_value) && isnan(other_value)); |
| 809 } |
| 810 if (IsString() && other->IsString()) { |
| 811 return String::cast(this)->Equals(String::cast(other)); |
| 812 } |
| 813 return false; |
| 814 } |
| 815 |
| 816 |
| 703 void Object::ShortPrint(FILE* out) { | 817 void Object::ShortPrint(FILE* out) { |
| 704 HeapStringAllocator allocator; | 818 HeapStringAllocator allocator; |
| 705 StringStream accumulator(&allocator); | 819 StringStream accumulator(&allocator); |
| 706 ShortPrint(&accumulator); | 820 ShortPrint(&accumulator); |
| 707 accumulator.OutputToFile(out); | 821 accumulator.OutputToFile(out); |
| 708 } | 822 } |
| 709 | 823 |
| 710 | 824 |
| 711 void Object::ShortPrint(StringStream* accumulator) { | 825 void Object::ShortPrint(StringStream* accumulator) { |
| 712 if (IsSmi()) { | 826 if (IsSmi()) { |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1067 accumulator->Add(" value = "); | 1181 accumulator->Add(" value = "); |
| 1068 JSValue::cast(this)->value()->ShortPrint(accumulator); | 1182 JSValue::cast(this)->value()->ShortPrint(accumulator); |
| 1069 } | 1183 } |
| 1070 accumulator->Put('>'); | 1184 accumulator->Put('>'); |
| 1071 break; | 1185 break; |
| 1072 } | 1186 } |
| 1073 } | 1187 } |
| 1074 } | 1188 } |
| 1075 | 1189 |
| 1076 | 1190 |
| 1191 void JSObject::PrintElementsTransition( |
| 1192 FILE* file, ElementsKind from_kind, FixedArrayBase* from_elements, |
| 1193 ElementsKind to_kind, FixedArrayBase* to_elements) { |
| 1194 if (from_kind != to_kind) { |
| 1195 PrintF(file, "elements transition ["); |
| 1196 PrintElementsKind(file, from_kind); |
| 1197 PrintF(file, " -> "); |
| 1198 PrintElementsKind(file, to_kind); |
| 1199 PrintF(file, "] in "); |
| 1200 JavaScriptFrame::PrintTop(file, false, true); |
| 1201 PrintF(file, " for "); |
| 1202 ShortPrint(file); |
| 1203 PrintF(file, " from "); |
| 1204 from_elements->ShortPrint(file); |
| 1205 PrintF(file, " to "); |
| 1206 to_elements->ShortPrint(file); |
| 1207 PrintF(file, "\n"); |
| 1208 } |
| 1209 } |
| 1210 |
| 1211 |
| 1077 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { | 1212 void HeapObject::HeapObjectShortPrint(StringStream* accumulator) { |
| 1078 Heap* heap = GetHeap(); | 1213 Heap* heap = GetHeap(); |
| 1079 if (!heap->Contains(this)) { | 1214 if (!heap->Contains(this)) { |
| 1080 accumulator->Add("!!!INVALID POINTER!!!"); | 1215 accumulator->Add("!!!INVALID POINTER!!!"); |
| 1081 return; | 1216 return; |
| 1082 } | 1217 } |
| 1083 if (!heap->Contains(map())) { | 1218 if (!heap->Contains(map())) { |
| 1084 accumulator->Add("!!!INVALID MAP!!!"); | 1219 accumulator->Add("!!!INVALID MAP!!!"); |
| 1085 return; | 1220 return; |
| 1086 } | 1221 } |
| 1087 | 1222 |
| 1088 accumulator->Add("%p ", this); | 1223 accumulator->Add("%p ", this); |
| 1089 | 1224 |
| 1090 if (IsString()) { | 1225 if (IsString()) { |
| 1091 String::cast(this)->StringShortPrint(accumulator); | 1226 String::cast(this)->StringShortPrint(accumulator); |
| 1092 return; | 1227 return; |
| 1093 } | 1228 } |
| 1094 if (IsJSObject()) { | 1229 if (IsJSObject()) { |
| 1095 JSObject::cast(this)->JSObjectShortPrint(accumulator); | 1230 JSObject::cast(this)->JSObjectShortPrint(accumulator); |
| 1096 return; | 1231 return; |
| 1097 } | 1232 } |
| 1098 switch (map()->instance_type()) { | 1233 switch (map()->instance_type()) { |
| 1099 case MAP_TYPE: | 1234 case MAP_TYPE: |
| 1100 accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind()); | 1235 accumulator->Add("<Map(elements=%u)>", Map::cast(this)->elements_kind()); |
| 1101 break; | 1236 break; |
| 1102 case FIXED_ARRAY_TYPE: | 1237 case FIXED_ARRAY_TYPE: |
| 1103 accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length()); | 1238 accumulator->Add("<FixedArray[%u]>", FixedArray::cast(this)->length()); |
| 1104 break; | 1239 break; |
| 1240 case FIXED_DOUBLE_ARRAY_TYPE: |
| 1241 accumulator->Add("<FixedDoubleArray[%u]>", |
| 1242 FixedDoubleArray::cast(this)->length()); |
| 1243 break; |
| 1105 case BYTE_ARRAY_TYPE: | 1244 case BYTE_ARRAY_TYPE: |
| 1106 accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length()); | 1245 accumulator->Add("<ByteArray[%u]>", ByteArray::cast(this)->length()); |
| 1107 break; | 1246 break; |
| 1108 case FREE_SPACE_TYPE: | 1247 case FREE_SPACE_TYPE: |
| 1109 accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size()); | 1248 accumulator->Add("<FreeSpace[%u]>", FreeSpace::cast(this)->Size()); |
| 1110 break; | 1249 break; |
| 1111 case EXTERNAL_PIXEL_ARRAY_TYPE: | 1250 case EXTERNAL_PIXEL_ARRAY_TYPE: |
| 1112 accumulator->Add("<ExternalPixelArray[%u]>", | 1251 accumulator->Add("<ExternalPixelArray[%u]>", |
| 1113 ExternalPixelArray::cast(this)->length()); | 1252 ExternalPixelArray::cast(this)->length()); |
| 1114 break; | 1253 break; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1240 switch (type) { | 1379 switch (type) { |
| 1241 case FIXED_ARRAY_TYPE: | 1380 case FIXED_ARRAY_TYPE: |
| 1242 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); | 1381 FixedArray::BodyDescriptor::IterateBody(this, object_size, v); |
| 1243 break; | 1382 break; |
| 1244 case FIXED_DOUBLE_ARRAY_TYPE: | 1383 case FIXED_DOUBLE_ARRAY_TYPE: |
| 1245 break; | 1384 break; |
| 1246 case JS_OBJECT_TYPE: | 1385 case JS_OBJECT_TYPE: |
| 1247 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: | 1386 case JS_CONTEXT_EXTENSION_OBJECT_TYPE: |
| 1248 case JS_VALUE_TYPE: | 1387 case JS_VALUE_TYPE: |
| 1249 case JS_ARRAY_TYPE: | 1388 case JS_ARRAY_TYPE: |
| 1389 case JS_SET_TYPE: |
| 1390 case JS_MAP_TYPE: |
| 1250 case JS_WEAK_MAP_TYPE: | 1391 case JS_WEAK_MAP_TYPE: |
| 1251 case JS_REGEXP_TYPE: | 1392 case JS_REGEXP_TYPE: |
| 1252 case JS_GLOBAL_PROXY_TYPE: | 1393 case JS_GLOBAL_PROXY_TYPE: |
| 1253 case JS_GLOBAL_OBJECT_TYPE: | 1394 case JS_GLOBAL_OBJECT_TYPE: |
| 1254 case JS_BUILTINS_OBJECT_TYPE: | 1395 case JS_BUILTINS_OBJECT_TYPE: |
| 1255 case JS_MESSAGE_OBJECT_TYPE: | 1396 case JS_MESSAGE_OBJECT_TYPE: |
| 1256 JSObject::BodyDescriptor::IterateBody(this, object_size, v); | 1397 JSObject::BodyDescriptor::IterateBody(this, object_size, v); |
| 1257 break; | 1398 break; |
| 1258 case JS_FUNCTION_TYPE: | 1399 case JS_FUNCTION_TYPE: |
| 1259 reinterpret_cast<JSFunction*>(this) | 1400 reinterpret_cast<JSFunction*>(this) |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1651 return AddSlowProperty(name, value, attributes); | 1792 return AddSlowProperty(name, value, attributes); |
| 1652 } | 1793 } |
| 1653 | 1794 |
| 1654 | 1795 |
| 1655 MaybeObject* JSObject::SetPropertyPostInterceptor( | 1796 MaybeObject* JSObject::SetPropertyPostInterceptor( |
| 1656 String* name, | 1797 String* name, |
| 1657 Object* value, | 1798 Object* value, |
| 1658 PropertyAttributes attributes, | 1799 PropertyAttributes attributes, |
| 1659 StrictModeFlag strict_mode) { | 1800 StrictModeFlag strict_mode) { |
| 1660 // Check local property, ignore interceptor. | 1801 // Check local property, ignore interceptor. |
| 1661 LookupResult result; | 1802 LookupResult result(GetIsolate()); |
| 1662 LocalLookupRealNamedProperty(name, &result); | 1803 LocalLookupRealNamedProperty(name, &result); |
| 1663 if (result.IsFound()) { | 1804 if (result.IsFound()) { |
| 1664 // An existing property, a map transition or a null descriptor was | 1805 // An existing property, a map transition or a null descriptor was |
| 1665 // found. Use set property to handle all these cases. | 1806 // found. Use set property to handle all these cases. |
| 1666 return SetProperty(&result, name, value, attributes, strict_mode); | 1807 return SetProperty(&result, name, value, attributes, strict_mode); |
| 1667 } | 1808 } |
| 1668 bool found = false; | 1809 bool found = false; |
| 1669 MaybeObject* result_object; | 1810 MaybeObject* result_object; |
| 1670 result_object = SetPropertyWithCallbackSetterInPrototypes(name, | 1811 result_object = SetPropertyWithCallbackSetterInPrototypes(name, |
| 1671 value, | 1812 value, |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1833 strict_mode); | 1974 strict_mode); |
| 1834 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 1975 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 1835 return raw_result; | 1976 return raw_result; |
| 1836 } | 1977 } |
| 1837 | 1978 |
| 1838 | 1979 |
| 1839 MaybeObject* JSReceiver::SetProperty(String* name, | 1980 MaybeObject* JSReceiver::SetProperty(String* name, |
| 1840 Object* value, | 1981 Object* value, |
| 1841 PropertyAttributes attributes, | 1982 PropertyAttributes attributes, |
| 1842 StrictModeFlag strict_mode) { | 1983 StrictModeFlag strict_mode) { |
| 1843 LookupResult result; | 1984 LookupResult result(GetIsolate()); |
| 1844 LocalLookup(name, &result); | 1985 LocalLookup(name, &result); |
| 1845 return SetProperty(&result, name, value, attributes, strict_mode); | 1986 return SetProperty(&result, name, value, attributes, strict_mode); |
| 1846 } | 1987 } |
| 1847 | 1988 |
| 1848 | 1989 |
| 1849 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | 1990 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, |
| 1850 String* name, | 1991 String* name, |
| 1851 Object* value, | 1992 Object* value, |
| 1852 JSObject* holder, | 1993 JSObject* holder, |
| 1853 StrictModeFlag strict_mode) { | 1994 StrictModeFlag strict_mode) { |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1999 *found = false; | 2140 *found = false; |
| 2000 return heap->the_hole_value(); | 2141 return heap->the_hole_value(); |
| 2001 } | 2142 } |
| 2002 | 2143 |
| 2003 MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes( | 2144 MaybeObject* JSObject::SetPropertyWithCallbackSetterInPrototypes( |
| 2004 String* name, | 2145 String* name, |
| 2005 Object* value, | 2146 Object* value, |
| 2006 PropertyAttributes attributes, | 2147 PropertyAttributes attributes, |
| 2007 bool* found, | 2148 bool* found, |
| 2008 StrictModeFlag strict_mode) { | 2149 StrictModeFlag strict_mode) { |
| 2009 LookupResult result; | 2150 Heap* heap = GetHeap(); |
| 2151 LookupResult result(heap->isolate()); |
| 2010 LookupCallbackSetterInPrototypes(name, &result); | 2152 LookupCallbackSetterInPrototypes(name, &result); |
| 2011 Heap* heap = GetHeap(); | |
| 2012 if (result.IsFound()) { | 2153 if (result.IsFound()) { |
| 2013 *found = true; | 2154 *found = true; |
| 2014 if (result.type() == CALLBACKS) { | 2155 if (result.type() == CALLBACKS) { |
| 2015 return SetPropertyWithCallback(result.GetCallbackObject(), | 2156 return SetPropertyWithCallback(result.GetCallbackObject(), |
| 2016 name, | 2157 name, |
| 2017 value, | 2158 value, |
| 2018 result.holder(), | 2159 result.holder(), |
| 2019 strict_mode); | 2160 strict_mode); |
| 2020 } else if (result.type() == HANDLER) { | 2161 } else if (result.type() == HANDLER) { |
| 2021 // We could not find a local property so let's check whether there is an | 2162 // We could not find a local property so let's check whether there is an |
| 2022 // accessor that wants to handle the property. | 2163 // accessor that wants to handle the property. |
| 2023 LookupResult accessor_result; | 2164 LookupResult accessor_result(heap->isolate()); |
| 2024 LookupCallbackSetterInPrototypes(name, &accessor_result); | 2165 LookupCallbackSetterInPrototypes(name, &accessor_result); |
| 2025 if (accessor_result.IsFound()) { | 2166 if (accessor_result.IsFound()) { |
| 2026 if (accessor_result.type() == CALLBACKS) { | 2167 if (accessor_result.type() == CALLBACKS) { |
| 2027 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), | 2168 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), |
| 2028 name, | 2169 name, |
| 2029 value, | 2170 value, |
| 2030 accessor_result.holder(), | 2171 accessor_result.holder(), |
| 2031 strict_mode); | 2172 strict_mode); |
| 2032 } else if (accessor_result.type() == HANDLER) { | 2173 } else if (accessor_result.type() == HANDLER) { |
| 2033 // There is a proxy in the prototype chain. Invoke its | 2174 // There is a proxy in the prototype chain. Invoke its |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2078 cache->Update(descriptors, name, number); | 2219 cache->Update(descriptors, name, number); |
| 2079 } | 2220 } |
| 2080 if (number != DescriptorArray::kNotFound) { | 2221 if (number != DescriptorArray::kNotFound) { |
| 2081 result->DescriptorResult(holder, descriptors->GetDetails(number), number); | 2222 result->DescriptorResult(holder, descriptors->GetDetails(number), number); |
| 2082 } else { | 2223 } else { |
| 2083 result->NotFound(); | 2224 result->NotFound(); |
| 2084 } | 2225 } |
| 2085 } | 2226 } |
| 2086 | 2227 |
| 2087 | 2228 |
| 2229 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { |
| 2230 ASSERT(!map.is_null()); |
| 2231 for (int i = 0; i < maps->length(); ++i) { |
| 2232 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true; |
| 2233 } |
| 2234 return false; |
| 2235 } |
| 2236 |
| 2237 |
| 2238 template <class T> |
| 2239 static Handle<T> MaybeNull(T* p) { |
| 2240 if (p == NULL) return Handle<T>::null(); |
| 2241 return Handle<T>(p); |
| 2242 } |
| 2243 |
| 2244 |
| 2245 Handle<Map> Map::FindTransitionedMap(MapHandleList* candidates) { |
| 2246 ElementsKind elms_kind = elements_kind(); |
| 2247 if (elms_kind == FAST_DOUBLE_ELEMENTS) { |
| 2248 bool dummy = true; |
| 2249 Handle<Map> fast_map = |
| 2250 MaybeNull(LookupElementsTransitionMap(FAST_ELEMENTS, &dummy)); |
| 2251 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { |
| 2252 return fast_map; |
| 2253 } |
| 2254 return Handle<Map>::null(); |
| 2255 } |
| 2256 if (elms_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 2257 bool dummy = true; |
| 2258 Handle<Map> double_map = |
| 2259 MaybeNull(LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS, &dummy)); |
| 2260 // In the current implementation, if the DOUBLE map doesn't exist, the |
| 2261 // FAST map can't exist either. |
| 2262 if (double_map.is_null()) return Handle<Map>::null(); |
| 2263 Handle<Map> fast_map = |
| 2264 MaybeNull(double_map->LookupElementsTransitionMap(FAST_ELEMENTS, |
| 2265 &dummy)); |
| 2266 if (!fast_map.is_null() && ContainsMap(candidates, fast_map)) { |
| 2267 return fast_map; |
| 2268 } |
| 2269 if (ContainsMap(candidates, double_map)) return double_map; |
| 2270 } |
| 2271 return Handle<Map>::null(); |
| 2272 } |
| 2273 |
| 2088 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, | 2274 static Map* GetElementsTransitionMapFromDescriptor(Object* descriptor_contents, |
| 2089 ElementsKind elements_kind) { | 2275 ElementsKind elements_kind) { |
| 2090 if (descriptor_contents->IsMap()) { | 2276 if (descriptor_contents->IsMap()) { |
| 2091 Map* map = Map::cast(descriptor_contents); | 2277 Map* map = Map::cast(descriptor_contents); |
| 2092 if (map->elements_kind() == elements_kind) { | 2278 if (map->elements_kind() == elements_kind) { |
| 2093 return map; | 2279 return map; |
| 2094 } | 2280 } |
| 2095 return NULL; | 2281 return NULL; |
| 2096 } | 2282 } |
| 2097 | 2283 |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2261 MaybeObject* maybe_new_descriptors = | 2447 MaybeObject* maybe_new_descriptors = |
| 2262 instance_descriptors()->CopyInsert(&desc, KEEP_TRANSITIONS); | 2448 instance_descriptors()->CopyInsert(&desc, KEEP_TRANSITIONS); |
| 2263 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { | 2449 if (!maybe_new_descriptors->ToObject(&new_descriptors)) { |
| 2264 return maybe_new_descriptors; | 2450 return maybe_new_descriptors; |
| 2265 } | 2451 } |
| 2266 set_instance_descriptors(DescriptorArray::cast(new_descriptors)); | 2452 set_instance_descriptors(DescriptorArray::cast(new_descriptors)); |
| 2267 return this; | 2453 return this; |
| 2268 } | 2454 } |
| 2269 | 2455 |
| 2270 | 2456 |
| 2457 Handle<Map> JSObject::GetElementsTransitionMap(Handle<JSObject> object, |
| 2458 ElementsKind to_kind) { |
| 2459 Isolate* isolate = object->GetIsolate(); |
| 2460 CALL_HEAP_FUNCTION(isolate, |
| 2461 object->GetElementsTransitionMap(to_kind), |
| 2462 Map); |
| 2463 } |
| 2464 |
| 2465 |
| 2271 MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind to_kind) { | 2466 MaybeObject* JSObject::GetElementsTransitionMap(ElementsKind to_kind) { |
| 2272 Map* current_map = map(); | 2467 Map* current_map = map(); |
| 2273 ElementsKind from_kind = current_map->elements_kind(); | 2468 ElementsKind from_kind = current_map->elements_kind(); |
| 2274 | 2469 |
| 2275 if (from_kind == to_kind) return current_map; | 2470 if (from_kind == to_kind) return current_map; |
| 2276 | 2471 |
| 2277 // Only objects with FastProperties can have DescriptorArrays and can track | 2472 // Only objects with FastProperties can have DescriptorArrays and can track |
| 2278 // element-related maps. Also don't add descriptors to maps that are shared. | 2473 // element-related maps. Also don't add descriptors to maps that are shared. |
| 2279 bool safe_to_add_transition = HasFastProperties() && | 2474 bool safe_to_add_transition = HasFastProperties() && |
| 2280 !current_map->IsUndefined() && | 2475 !current_map->IsUndefined() && |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2416 value, | 2611 value, |
| 2417 result->holder(), | 2612 result->holder(), |
| 2418 strict_mode); | 2613 strict_mode); |
| 2419 } | 2614 } |
| 2420 } | 2615 } |
| 2421 break; | 2616 break; |
| 2422 } | 2617 } |
| 2423 case INTERCEPTOR: { | 2618 case INTERCEPTOR: { |
| 2424 // Try lookup real named properties. Note that only property can be | 2619 // Try lookup real named properties. Note that only property can be |
| 2425 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. | 2620 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. |
| 2426 LookupResult r; | 2621 LookupResult r(GetIsolate()); |
| 2427 LookupRealNamedProperty(name, &r); | 2622 LookupRealNamedProperty(name, &r); |
| 2428 if (r.IsProperty()) { | 2623 if (r.IsProperty()) { |
| 2429 return SetPropertyWithFailedAccessCheck(&r, | 2624 return SetPropertyWithFailedAccessCheck(&r, |
| 2430 name, | 2625 name, |
| 2431 value, | 2626 value, |
| 2432 check_prototype, | 2627 check_prototype, |
| 2433 strict_mode); | 2628 strict_mode); |
| 2434 } | 2629 } |
| 2435 break; | 2630 break; |
| 2436 } | 2631 } |
| 2437 default: { | 2632 default: { |
| 2438 break; | 2633 break; |
| 2439 } | 2634 } |
| 2440 } | 2635 } |
| 2441 } | 2636 } |
| 2442 } | 2637 } |
| 2443 | 2638 |
| 2444 Heap* heap = GetHeap(); | 2639 Isolate* isolate = GetIsolate(); |
| 2445 HandleScope scope(heap->isolate()); | 2640 HandleScope scope(isolate); |
| 2446 Handle<Object> value_handle(value); | 2641 Handle<Object> value_handle(value); |
| 2447 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 2642 isolate->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 2448 return *value_handle; | 2643 return *value_handle; |
| 2449 } | 2644 } |
| 2450 | 2645 |
| 2451 | 2646 |
| 2452 MaybeObject* JSReceiver::SetProperty(LookupResult* result, | 2647 MaybeObject* JSReceiver::SetProperty(LookupResult* result, |
| 2453 String* key, | 2648 String* key, |
| 2454 Object* value, | 2649 Object* value, |
| 2455 PropertyAttributes attributes, | 2650 PropertyAttributes attributes, |
| 2456 StrictModeFlag strict_mode) { | 2651 StrictModeFlag strict_mode) { |
| 2457 if (result->IsFound() && result->type() == HANDLER) { | 2652 if (result->IsFound() && result->type() == HANDLER) { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2500 | 2695 |
| 2501 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandlerIfDefiningSetter( | 2696 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandlerIfDefiningSetter( |
| 2502 String* name_raw, | 2697 String* name_raw, |
| 2503 Object* value_raw, | 2698 Object* value_raw, |
| 2504 PropertyAttributes attributes, | 2699 PropertyAttributes attributes, |
| 2505 StrictModeFlag strict_mode, | 2700 StrictModeFlag strict_mode, |
| 2506 bool* found) { | 2701 bool* found) { |
| 2507 *found = true; // except where defined otherwise... | 2702 *found = true; // except where defined otherwise... |
| 2508 Isolate* isolate = GetHeap()->isolate(); | 2703 Isolate* isolate = GetHeap()->isolate(); |
| 2509 Handle<JSProxy> proxy(this); | 2704 Handle<JSProxy> proxy(this); |
| 2705 Handle<Object> handler(this->handler()); // Trap might morph proxy. |
| 2510 Handle<String> name(name_raw); | 2706 Handle<String> name(name_raw); |
| 2511 Handle<Object> value(value_raw); | 2707 Handle<Object> value(value_raw); |
| 2512 Handle<Object> args[] = { name }; | 2708 Handle<Object> args[] = { name }; |
| 2513 Handle<Object> result = proxy->CallTrap( | 2709 Handle<Object> result = proxy->CallTrap( |
| 2514 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); | 2710 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); |
| 2515 if (isolate->has_pending_exception()) return Failure::Exception(); | 2711 if (isolate->has_pending_exception()) return Failure::Exception(); |
| 2516 | 2712 |
| 2517 if (!result->IsUndefined()) { | 2713 if (!result->IsUndefined()) { |
| 2518 // The proxy handler cares about this property. | 2714 // The proxy handler cares about this property. |
| 2519 // Check whether it is virtualized as an accessor. | 2715 // Check whether it is virtualized as an accessor. |
| 2520 // Emulate [[GetProperty]] semantics for proxies. | 2716 // Emulate [[GetProperty]] semantics for proxies. |
| 2521 bool has_pending_exception; | 2717 bool has_pending_exception; |
| 2522 Handle<Object> argv[] = { result }; | 2718 Handle<Object> argv[] = { result }; |
| 2523 Handle<Object> desc = | 2719 Handle<Object> desc = |
| 2524 Execution::Call(isolate->to_complete_property_descriptor(), result, | 2720 Execution::Call(isolate->to_complete_property_descriptor(), result, |
| 2525 ARRAY_SIZE(argv), argv, &has_pending_exception); | 2721 ARRAY_SIZE(argv), argv, &has_pending_exception); |
| 2526 if (has_pending_exception) return Failure::Exception(); | 2722 if (has_pending_exception) return Failure::Exception(); |
| 2527 | 2723 |
| 2528 Handle<String> conf_name = | 2724 Handle<String> conf_name = |
| 2529 isolate->factory()->LookupAsciiSymbol("configurable_"); | 2725 isolate->factory()->LookupAsciiSymbol("configurable_"); |
| 2530 Handle<Object> configurable(v8::internal::GetProperty(desc, conf_name)); | 2726 Handle<Object> configurable(v8::internal::GetProperty(desc, conf_name)); |
| 2531 ASSERT(!isolate->has_pending_exception()); | 2727 ASSERT(!isolate->has_pending_exception()); |
| 2532 if (configurable->IsFalse()) { | 2728 if (configurable->IsFalse()) { |
| 2533 Handle<Object> args[] = { Handle<Object>(proxy->handler()), proxy, name }; | 2729 Handle<String> trap = |
| 2730 isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor"); |
| 2731 Handle<Object> args[] = { handler, trap, name }; |
| 2534 Handle<Object> error = isolate->factory()->NewTypeError( | 2732 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2535 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); | 2733 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); |
| 2536 return isolate->Throw(*error); | 2734 return isolate->Throw(*error); |
| 2537 } | 2735 } |
| 2538 ASSERT(configurable->IsTrue()); | 2736 ASSERT(configurable->IsTrue()); |
| 2539 | 2737 |
| 2540 // Check for AccessorDescriptor. | 2738 // Check for AccessorDescriptor. |
| 2541 Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_"); | 2739 Handle<String> set_name = isolate->factory()->LookupAsciiSymbol("set_"); |
| 2542 Handle<Object> setter(v8::internal::GetProperty(desc, set_name)); | 2740 Handle<Object> setter(v8::internal::GetProperty(desc, set_name)); |
| 2543 ASSERT(!isolate->has_pending_exception()); | 2741 ASSERT(!isolate->has_pending_exception()); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2603 return JSProxy::DeletePropertyWithHandler(*name, mode); | 2801 return JSProxy::DeletePropertyWithHandler(*name, mode); |
| 2604 } | 2802 } |
| 2605 | 2803 |
| 2606 | 2804 |
| 2607 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( | 2805 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( |
| 2608 JSReceiver* receiver_raw, | 2806 JSReceiver* receiver_raw, |
| 2609 String* name_raw) { | 2807 String* name_raw) { |
| 2610 Isolate* isolate = GetIsolate(); | 2808 Isolate* isolate = GetIsolate(); |
| 2611 HandleScope scope(isolate); | 2809 HandleScope scope(isolate); |
| 2612 Handle<JSProxy> proxy(this); | 2810 Handle<JSProxy> proxy(this); |
| 2811 Handle<Object> handler(this->handler()); // Trap might morph proxy. |
| 2613 Handle<JSReceiver> receiver(receiver_raw); | 2812 Handle<JSReceiver> receiver(receiver_raw); |
| 2614 Handle<Object> name(name_raw); | 2813 Handle<Object> name(name_raw); |
| 2615 | 2814 |
| 2616 Handle<Object> args[] = { name }; | 2815 Handle<Object> args[] = { name }; |
| 2617 Handle<Object> result = CallTrap( | 2816 Handle<Object> result = CallTrap( |
| 2618 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); | 2817 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); |
| 2619 if (isolate->has_pending_exception()) return NONE; | 2818 if (isolate->has_pending_exception()) return NONE; |
| 2620 | 2819 |
| 2621 if (result->IsUndefined()) return ABSENT; | 2820 if (result->IsUndefined()) return ABSENT; |
| 2622 | 2821 |
| 2623 bool has_pending_exception; | 2822 bool has_pending_exception; |
| 2624 Handle<Object> argv[] = { result }; | 2823 Handle<Object> argv[] = { result }; |
| 2625 Handle<Object> desc = | 2824 Handle<Object> desc = |
| 2626 Execution::Call(isolate->to_complete_property_descriptor(), result, | 2825 Execution::Call(isolate->to_complete_property_descriptor(), result, |
| 2627 ARRAY_SIZE(argv), argv, &has_pending_exception); | 2826 ARRAY_SIZE(argv), argv, &has_pending_exception); |
| 2628 if (has_pending_exception) return NONE; | 2827 if (has_pending_exception) return NONE; |
| 2629 | 2828 |
| 2630 // Convert result to PropertyAttributes. | 2829 // Convert result to PropertyAttributes. |
| 2631 Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable"); | 2830 Handle<String> enum_n = isolate->factory()->LookupAsciiSymbol("enumerable"); |
| 2632 Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n)); | 2831 Handle<Object> enumerable(v8::internal::GetProperty(desc, enum_n)); |
| 2633 if (isolate->has_pending_exception()) return NONE; | 2832 if (isolate->has_pending_exception()) return NONE; |
| 2634 Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable"); | 2833 Handle<String> conf_n = isolate->factory()->LookupAsciiSymbol("configurable"); |
| 2635 Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n)); | 2834 Handle<Object> configurable(v8::internal::GetProperty(desc, conf_n)); |
| 2636 if (isolate->has_pending_exception()) return NONE; | 2835 if (isolate->has_pending_exception()) return NONE; |
| 2637 Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable"); | 2836 Handle<String> writ_n = isolate->factory()->LookupAsciiSymbol("writable"); |
| 2638 Handle<Object> writable(v8::internal::GetProperty(desc, writ_n)); | 2837 Handle<Object> writable(v8::internal::GetProperty(desc, writ_n)); |
| 2639 if (isolate->has_pending_exception()) return NONE; | 2838 if (isolate->has_pending_exception()) return NONE; |
| 2640 | 2839 |
| 2641 if (configurable->IsFalse()) { | 2840 if (configurable->IsFalse()) { |
| 2642 Handle<Object> args[] = { Handle<Object>(proxy->handler()), proxy, name }; | 2841 Handle<String> trap = |
| 2842 isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor"); |
| 2843 Handle<Object> args[] = { handler, trap, name }; |
| 2643 Handle<Object> error = isolate->factory()->NewTypeError( | 2844 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2644 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); | 2845 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); |
| 2645 isolate->Throw(*error); | 2846 isolate->Throw(*error); |
| 2646 return NONE; | 2847 return NONE; |
| 2647 } | 2848 } |
| 2648 | 2849 |
| 2649 int attributes = NONE; | 2850 int attributes = NONE; |
| 2650 if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM; | 2851 if (enumerable->ToBoolean()->IsFalse()) attributes |= DONT_ENUM; |
| 2651 if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE; | 2852 if (configurable->ToBoolean()->IsFalse()) attributes |= DONT_DELETE; |
| 2652 if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY; | 2853 if (writable->ToBoolean()->IsFalse()) attributes |= READ_ONLY; |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2852 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" | 3053 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" |
| 2853 // doesn't handle function prototypes correctly. | 3054 // doesn't handle function prototypes correctly. |
| 2854 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( | 3055 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
| 2855 String* name, | 3056 String* name, |
| 2856 Object* value, | 3057 Object* value, |
| 2857 PropertyAttributes attributes) { | 3058 PropertyAttributes attributes) { |
| 2858 | 3059 |
| 2859 // Make sure that the top context does not change when doing callbacks or | 3060 // Make sure that the top context does not change when doing callbacks or |
| 2860 // interceptor calls. | 3061 // interceptor calls. |
| 2861 AssertNoContextChange ncc; | 3062 AssertNoContextChange ncc; |
| 2862 LookupResult result; | 3063 Isolate* isolate = GetIsolate(); |
| 3064 LookupResult result(isolate); |
| 2863 LocalLookup(name, &result); | 3065 LocalLookup(name, &result); |
| 2864 // Check access rights if needed. | 3066 // Check access rights if needed. |
| 2865 if (IsAccessCheckNeeded()) { | 3067 if (IsAccessCheckNeeded()) { |
| 2866 Heap* heap = GetHeap(); | 3068 if (!isolate->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 2867 if (!heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { | |
| 2868 return SetPropertyWithFailedAccessCheck(&result, | 3069 return SetPropertyWithFailedAccessCheck(&result, |
| 2869 name, | 3070 name, |
| 2870 value, | 3071 value, |
| 2871 false, | 3072 false, |
| 2872 kNonStrictMode); | 3073 kNonStrictMode); |
| 2873 } | 3074 } |
| 2874 } | 3075 } |
| 2875 | 3076 |
| 2876 if (IsJSGlobalProxy()) { | 3077 if (IsJSGlobalProxy()) { |
| 2877 Object* proto = GetPrototype(); | 3078 Object* proto = GetPrototype(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2928 UNREACHABLE(); | 3129 UNREACHABLE(); |
| 2929 return value; | 3130 return value; |
| 2930 } | 3131 } |
| 2931 | 3132 |
| 2932 | 3133 |
| 2933 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 3134 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
| 2934 JSObject* receiver, | 3135 JSObject* receiver, |
| 2935 String* name, | 3136 String* name, |
| 2936 bool continue_search) { | 3137 bool continue_search) { |
| 2937 // Check local property, ignore interceptor. | 3138 // Check local property, ignore interceptor. |
| 2938 LookupResult result; | 3139 LookupResult result(GetIsolate()); |
| 2939 LocalLookupRealNamedProperty(name, &result); | 3140 LocalLookupRealNamedProperty(name, &result); |
| 2940 if (result.IsProperty()) return result.GetAttributes(); | 3141 if (result.IsProperty()) return result.GetAttributes(); |
| 2941 | 3142 |
| 2942 if (continue_search) { | 3143 if (continue_search) { |
| 2943 // Continue searching via the prototype chain. | 3144 // Continue searching via the prototype chain. |
| 2944 Object* pt = GetPrototype(); | 3145 Object* pt = GetPrototype(); |
| 2945 if (!pt->IsNull()) { | 3146 if (!pt->IsNull()) { |
| 2946 return JSObject::cast(pt)-> | 3147 return JSObject::cast(pt)-> |
| 2947 GetPropertyAttributeWithReceiver(receiver, name); | 3148 GetPropertyAttributeWithReceiver(receiver, name); |
| 2948 } | 3149 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3004 | 3205 |
| 3005 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( | 3206 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( |
| 3006 JSReceiver* receiver, | 3207 JSReceiver* receiver, |
| 3007 String* key) { | 3208 String* key) { |
| 3008 uint32_t index = 0; | 3209 uint32_t index = 0; |
| 3009 if (IsJSObject() && key->AsArrayIndex(&index)) { | 3210 if (IsJSObject() && key->AsArrayIndex(&index)) { |
| 3010 return JSObject::cast(this)->HasElementWithReceiver(receiver, index) | 3211 return JSObject::cast(this)->HasElementWithReceiver(receiver, index) |
| 3011 ? NONE : ABSENT; | 3212 ? NONE : ABSENT; |
| 3012 } | 3213 } |
| 3013 // Named property. | 3214 // Named property. |
| 3014 LookupResult result; | 3215 LookupResult result(GetIsolate()); |
| 3015 Lookup(key, &result); | 3216 Lookup(key, &result); |
| 3016 return GetPropertyAttribute(receiver, &result, key, true); | 3217 return GetPropertyAttribute(receiver, &result, key, true); |
| 3017 } | 3218 } |
| 3018 | 3219 |
| 3019 | 3220 |
| 3020 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver, | 3221 PropertyAttributes JSReceiver::GetPropertyAttribute(JSReceiver* receiver, |
| 3021 LookupResult* result, | 3222 LookupResult* result, |
| 3022 String* name, | 3223 String* name, |
| 3023 bool continue_search) { | 3224 bool continue_search) { |
| 3024 // Check access rights if needed. | 3225 // Check access rights if needed. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 3053 | 3254 |
| 3054 | 3255 |
| 3055 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) { | 3256 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(String* name) { |
| 3056 // Check whether the name is an array index. | 3257 // Check whether the name is an array index. |
| 3057 uint32_t index = 0; | 3258 uint32_t index = 0; |
| 3058 if (IsJSObject() && name->AsArrayIndex(&index)) { | 3259 if (IsJSObject() && name->AsArrayIndex(&index)) { |
| 3059 if (JSObject::cast(this)->HasLocalElement(index)) return NONE; | 3260 if (JSObject::cast(this)->HasLocalElement(index)) return NONE; |
| 3060 return ABSENT; | 3261 return ABSENT; |
| 3061 } | 3262 } |
| 3062 // Named property. | 3263 // Named property. |
| 3063 LookupResult result; | 3264 LookupResult result(GetIsolate()); |
| 3064 LocalLookup(name, &result); | 3265 LocalLookup(name, &result); |
| 3065 return GetPropertyAttribute(this, &result, name, false); | 3266 return GetPropertyAttribute(this, &result, name, false); |
| 3066 } | 3267 } |
| 3067 | 3268 |
| 3068 | 3269 |
| 3069 MaybeObject* NormalizedMapCache::Get(JSObject* obj, | 3270 MaybeObject* NormalizedMapCache::Get(JSObject* obj, |
| 3070 PropertyNormalizationMode mode) { | 3271 PropertyNormalizationMode mode) { |
| 3071 Isolate* isolate = obj->GetIsolate(); | 3272 Isolate* isolate = obj->GetIsolate(); |
| 3072 Map* fast = obj->map(); | 3273 Map* fast = obj->map(); |
| 3073 int index = fast->Hash() % kEntries; | 3274 int index = fast->Hash() % kEntries; |
| 3074 Object* result = get(index); | 3275 Object* result = get(index); |
| 3075 if (result->IsMap() && | 3276 if (result->IsMap() && |
| 3076 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { | 3277 Map::cast(result)->EquivalentToForNormalization(fast, mode)) { |
| 3077 #ifdef DEBUG | 3278 #ifdef DEBUG |
| 3078 Map::cast(result)->SharedMapVerify(); | 3279 if (FLAG_verify_heap) { |
| 3280 Map::cast(result)->SharedMapVerify(); |
| 3281 } |
| 3079 if (FLAG_enable_slow_asserts) { | 3282 if (FLAG_enable_slow_asserts) { |
| 3080 // The cached map should match newly created normalized map bit-by-bit. | 3283 // The cached map should match newly created normalized map bit-by-bit. |
| 3081 Object* fresh; | 3284 Object* fresh; |
| 3082 { MaybeObject* maybe_fresh = | 3285 { MaybeObject* maybe_fresh = |
| 3083 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); | 3286 fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); |
| 3084 if (maybe_fresh->ToObject(&fresh)) { | 3287 if (maybe_fresh->ToObject(&fresh)) { |
| 3085 ASSERT(memcmp(Map::cast(fresh)->address(), | 3288 ASSERT(memcmp(Map::cast(fresh)->address(), |
| 3086 Map::cast(result)->address(), | 3289 Map::cast(result)->address(), |
| 3087 Map::kSize) == 0); | 3290 Map::kSize) == 0); |
| 3088 } | 3291 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3104 | 3307 |
| 3105 | 3308 |
| 3106 void NormalizedMapCache::Clear() { | 3309 void NormalizedMapCache::Clear() { |
| 3107 int entries = length(); | 3310 int entries = length(); |
| 3108 for (int i = 0; i != entries; i++) { | 3311 for (int i = 0; i != entries; i++) { |
| 3109 set_undefined(i); | 3312 set_undefined(i); |
| 3110 } | 3313 } |
| 3111 } | 3314 } |
| 3112 | 3315 |
| 3113 | 3316 |
| 3317 void JSObject::UpdateMapCodeCache(Handle<JSObject> object, |
| 3318 Handle<String> name, |
| 3319 Handle<Code> code) { |
| 3320 Isolate* isolate = object->GetIsolate(); |
| 3321 CALL_HEAP_FUNCTION_VOID(isolate, |
| 3322 object->UpdateMapCodeCache(*name, *code)); |
| 3323 } |
| 3324 |
| 3325 |
| 3114 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { | 3326 MaybeObject* JSObject::UpdateMapCodeCache(String* name, Code* code) { |
| 3115 if (map()->is_shared()) { | 3327 if (map()->is_shared()) { |
| 3116 // Fast case maps are never marked as shared. | 3328 // Fast case maps are never marked as shared. |
| 3117 ASSERT(!HasFastProperties()); | 3329 ASSERT(!HasFastProperties()); |
| 3118 // Replace the map with an identical copy that can be safely modified. | 3330 // Replace the map with an identical copy that can be safely modified. |
| 3119 Object* obj; | 3331 Object* obj; |
| 3120 { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, | 3332 { MaybeObject* maybe_obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, |
| 3121 UNIQUE_NORMALIZED_MAP); | 3333 UNIQUE_NORMALIZED_MAP); |
| 3122 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3334 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3123 } | 3335 } |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3349 | 3561 |
| 3350 | 3562 |
| 3351 Smi* JSReceiver::GenerateIdentityHash() { | 3563 Smi* JSReceiver::GenerateIdentityHash() { |
| 3352 Isolate* isolate = GetIsolate(); | 3564 Isolate* isolate = GetIsolate(); |
| 3353 | 3565 |
| 3354 int hash_value; | 3566 int hash_value; |
| 3355 int attempts = 0; | 3567 int attempts = 0; |
| 3356 do { | 3568 do { |
| 3357 // Generate a random 32-bit hash value but limit range to fit | 3569 // Generate a random 32-bit hash value but limit range to fit |
| 3358 // within a smi. | 3570 // within a smi. |
| 3359 hash_value = V8::Random(isolate) & Smi::kMaxValue; | 3571 hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue; |
| 3360 attempts++; | 3572 attempts++; |
| 3361 } while (hash_value == 0 && attempts < 30); | 3573 } while (hash_value == 0 && attempts < 30); |
| 3362 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 | 3574 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
| 3363 | 3575 |
| 3364 return Smi::FromInt(hash_value); | 3576 return Smi::FromInt(hash_value); |
| 3365 } | 3577 } |
| 3366 | 3578 |
| 3367 | 3579 |
| 3368 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) { | 3580 MaybeObject* JSObject::SetIdentityHash(Object* hash, CreationFlag flag) { |
| 3369 MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(), | 3581 MaybeObject* maybe = SetHiddenProperty(GetHeap()->identity_hash_symbol(), |
| 3370 hash); | 3582 hash); |
| 3371 if (maybe->IsFailure()) return maybe; | 3583 if (maybe->IsFailure()) return maybe; |
| 3372 return this; | 3584 return this; |
| 3373 } | 3585 } |
| 3374 | 3586 |
| 3375 | 3587 |
| 3376 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) { | 3588 MaybeObject* JSObject::GetIdentityHash(CreationFlag flag) { |
| 3377 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol()); | 3589 Object* stored_value = GetHiddenProperty(GetHeap()->identity_hash_symbol()); |
| 3378 if (stored_value->IsSmi()) return stored_value; | 3590 if (stored_value->IsSmi()) return stored_value; |
| 3379 | 3591 |
| 3592 // Do not generate permanent identity hash code if not requested. |
| 3593 if (flag == OMIT_CREATION) return GetHeap()->undefined_value(); |
| 3594 |
| 3380 Smi* hash = GenerateIdentityHash(); | 3595 Smi* hash = GenerateIdentityHash(); |
| 3381 MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(), | 3596 MaybeObject* result = SetHiddenProperty(GetHeap()->identity_hash_symbol(), |
| 3382 hash); | 3597 hash); |
| 3383 if (result->IsFailure()) return result; | 3598 if (result->IsFailure()) return result; |
| 3384 if (result->ToObjectUnchecked()->IsUndefined()) { | 3599 if (result->ToObjectUnchecked()->IsUndefined()) { |
| 3385 // Trying to get hash of detached proxy. | 3600 // Trying to get hash of detached proxy. |
| 3386 return Smi::FromInt(0); | 3601 return Smi::FromInt(0); |
| 3387 } | 3602 } |
| 3388 return hash; | 3603 return hash; |
| 3389 } | 3604 } |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3560 DONT_ENUM, | 3775 DONT_ENUM, |
| 3561 kNonStrictMode); | 3776 kNonStrictMode); |
| 3562 if (store_result->IsFailure()) return store_result; | 3777 if (store_result->IsFailure()) return store_result; |
| 3563 return this; | 3778 return this; |
| 3564 } | 3779 } |
| 3565 | 3780 |
| 3566 | 3781 |
| 3567 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, | 3782 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, |
| 3568 DeleteMode mode) { | 3783 DeleteMode mode) { |
| 3569 // Check local property, ignore interceptor. | 3784 // Check local property, ignore interceptor. |
| 3570 LookupResult result; | 3785 LookupResult result(GetIsolate()); |
| 3571 LocalLookupRealNamedProperty(name, &result); | 3786 LocalLookupRealNamedProperty(name, &result); |
| 3572 if (!result.IsProperty()) return GetHeap()->true_value(); | 3787 if (!result.IsProperty()) return GetHeap()->true_value(); |
| 3573 | 3788 |
| 3574 // Normalize object if needed. | 3789 // Normalize object if needed. |
| 3575 Object* obj; | 3790 Object* obj; |
| 3576 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 3791 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 3577 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 3792 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 3578 } | 3793 } |
| 3579 | 3794 |
| 3580 return DeleteNormalizedProperty(name, mode); | 3795 return DeleteNormalizedProperty(name, mode); |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3709 Object* proto = GetPrototype(); | 3924 Object* proto = GetPrototype(); |
| 3710 if (proto->IsNull()) return isolate->heap()->false_value(); | 3925 if (proto->IsNull()) return isolate->heap()->false_value(); |
| 3711 ASSERT(proto->IsJSGlobalObject()); | 3926 ASSERT(proto->IsJSGlobalObject()); |
| 3712 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); | 3927 return JSGlobalObject::cast(proto)->DeleteProperty(name, mode); |
| 3713 } | 3928 } |
| 3714 | 3929 |
| 3715 uint32_t index = 0; | 3930 uint32_t index = 0; |
| 3716 if (name->AsArrayIndex(&index)) { | 3931 if (name->AsArrayIndex(&index)) { |
| 3717 return DeleteElement(index, mode); | 3932 return DeleteElement(index, mode); |
| 3718 } else { | 3933 } else { |
| 3719 LookupResult result; | 3934 LookupResult result(isolate); |
| 3720 LocalLookup(name, &result); | 3935 LocalLookup(name, &result); |
| 3721 if (!result.IsProperty()) return isolate->heap()->true_value(); | 3936 if (!result.IsProperty()) return isolate->heap()->true_value(); |
| 3722 // Ignore attributes if forcing a deletion. | 3937 // Ignore attributes if forcing a deletion. |
| 3723 if (result.IsDontDelete() && mode != FORCE_DELETION) { | 3938 if (result.IsDontDelete() && mode != FORCE_DELETION) { |
| 3724 if (mode == STRICT_DELETION) { | 3939 if (mode == STRICT_DELETION) { |
| 3725 // Deleting a non-configurable property in strict mode. | 3940 // Deleting a non-configurable property in strict mode. |
| 3726 HandleScope scope(isolate); | 3941 HandleScope scope(isolate); |
| 3727 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; | 3942 Handle<Object> args[2] = { Handle<Object>(name), Handle<Object>(this) }; |
| 3728 return isolate->Throw(*isolate->factory()->NewTypeError( | 3943 return isolate->Throw(*isolate->factory()->NewTypeError( |
| 3729 "strict_delete_property", HandleVector(args, 2))); | 3944 "strict_delete_property", HandleVector(args, 2))); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3920 if (!maybe->To<Map>(&new_map)) return maybe; | 4135 if (!maybe->To<Map>(&new_map)) return maybe; |
| 3921 } | 4136 } |
| 3922 new_map->set_is_extensible(false); | 4137 new_map->set_is_extensible(false); |
| 3923 set_map(new_map); | 4138 set_map(new_map); |
| 3924 ASSERT(!map()->is_extensible()); | 4139 ASSERT(!map()->is_extensible()); |
| 3925 return new_map; | 4140 return new_map; |
| 3926 } | 4141 } |
| 3927 | 4142 |
| 3928 | 4143 |
| 3929 // Tests for the fast common case for property enumeration: | 4144 // Tests for the fast common case for property enumeration: |
| 3930 // - This object and all prototypes has an enum cache (which means that it has | 4145 // - This object and all prototypes has an enum cache (which means that |
| 3931 // no interceptors and needs no access checks). | 4146 // it is no proxy, has no interceptors and needs no access checks). |
| 3932 // - This object has no elements. | 4147 // - This object has no elements. |
| 3933 // - No prototype has enumerable properties/elements. | 4148 // - No prototype has enumerable properties/elements. |
| 3934 bool JSObject::IsSimpleEnum() { | 4149 bool JSReceiver::IsSimpleEnum() { |
| 3935 Heap* heap = GetHeap(); | 4150 Heap* heap = GetHeap(); |
| 3936 for (Object* o = this; | 4151 for (Object* o = this; |
| 3937 o != heap->null_value(); | 4152 o != heap->null_value(); |
| 3938 o = JSObject::cast(o)->GetPrototype()) { | 4153 o = JSObject::cast(o)->GetPrototype()) { |
| 4154 if (!o->IsJSObject()) return false; |
| 3939 JSObject* curr = JSObject::cast(o); | 4155 JSObject* curr = JSObject::cast(o); |
| 3940 if (!curr->map()->instance_descriptors()->HasEnumCache()) return false; | 4156 if (!curr->map()->instance_descriptors()->HasEnumCache()) return false; |
| 3941 ASSERT(!curr->HasNamedInterceptor()); | 4157 ASSERT(!curr->HasNamedInterceptor()); |
| 3942 ASSERT(!curr->HasIndexedInterceptor()); | 4158 ASSERT(!curr->HasIndexedInterceptor()); |
| 3943 ASSERT(!curr->IsAccessCheckNeeded()); | 4159 ASSERT(!curr->IsAccessCheckNeeded()); |
| 3944 if (curr->NumberOfEnumElements() > 0) return false; | 4160 if (curr->NumberOfEnumElements() > 0) return false; |
| 3945 if (curr != this) { | 4161 if (curr != this) { |
| 3946 FixedArray* curr_fixed_array = | 4162 FixedArray* curr_fixed_array = |
| 3947 FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache()); | 4163 FixedArray::cast(curr->map()->instance_descriptors()->GetEnumCache()); |
| 3948 if (curr_fixed_array->length() > 0) return false; | 4164 if (curr_fixed_array->length() > 0) return false; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4058 for (Object* current = this; | 4274 for (Object* current = this; |
| 4059 current != heap->null_value() && current->IsJSObject(); | 4275 current != heap->null_value() && current->IsJSObject(); |
| 4060 current = JSObject::cast(current)->GetPrototype()) { | 4276 current = JSObject::cast(current)->GetPrototype()) { |
| 4061 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); | 4277 JSObject::cast(current)->LocalLookupRealNamedProperty(name, result); |
| 4062 if (result->IsProperty() && result->type() == CALLBACKS) return; | 4278 if (result->IsProperty() && result->type() == CALLBACKS) return; |
| 4063 } | 4279 } |
| 4064 result->NotFound(); | 4280 result->NotFound(); |
| 4065 } | 4281 } |
| 4066 | 4282 |
| 4067 | 4283 |
| 4068 // Search for a getter or setter in an elements dictionary. Returns either | 4284 // Search for a getter or setter in an elements dictionary and update its |
| 4069 // undefined if the element is read-only, or the getter/setter pair (fixed | 4285 // attributes. Returns either undefined if the element is read-only, or the |
| 4070 // array) if there is an existing one, or the hole value if the element does | 4286 // getter/setter pair (fixed array) if there is an existing one, or the hole |
| 4071 // not exist or is a normal non-getter/setter data element. | 4287 // value if the element does not exist or is a normal non-getter/setter data |
| 4072 static Object* FindGetterSetterInDictionary(NumberDictionary* dictionary, | 4288 // element. |
| 4073 uint32_t index, | 4289 static Object* UpdateGetterSetterInDictionary(NumberDictionary* dictionary, |
| 4074 Heap* heap) { | 4290 uint32_t index, |
| 4291 PropertyAttributes attributes, |
| 4292 Heap* heap) { |
| 4075 int entry = dictionary->FindEntry(index); | 4293 int entry = dictionary->FindEntry(index); |
| 4076 if (entry != NumberDictionary::kNotFound) { | 4294 if (entry != NumberDictionary::kNotFound) { |
| 4077 Object* result = dictionary->ValueAt(entry); | 4295 Object* result = dictionary->ValueAt(entry); |
| 4078 PropertyDetails details = dictionary->DetailsAt(entry); | 4296 PropertyDetails details = dictionary->DetailsAt(entry); |
| 4079 if (details.IsReadOnly()) return heap->undefined_value(); | 4297 if (details.IsReadOnly()) return heap->undefined_value(); |
| 4080 if (details.type() == CALLBACKS && result->IsFixedArray()) return result; | 4298 if (details.type() == CALLBACKS && result->IsFixedArray()) { |
| 4299 if (details.attributes() != attributes) { |
| 4300 dictionary->DetailsAtPut(entry, |
| 4301 PropertyDetails(attributes, CALLBACKS, index)); |
| 4302 } |
| 4303 return result; |
| 4304 } |
| 4081 } | 4305 } |
| 4082 return heap->the_hole_value(); | 4306 return heap->the_hole_value(); |
| 4083 } | 4307 } |
| 4084 | 4308 |
| 4085 | 4309 |
| 4086 MaybeObject* JSObject::DefineGetterSetter(String* name, | 4310 MaybeObject* JSObject::DefineGetterSetter(String* name, |
| 4087 PropertyAttributes attributes) { | 4311 PropertyAttributes attributes) { |
| 4088 Heap* heap = GetHeap(); | 4312 Heap* heap = GetHeap(); |
| 4089 // Make sure that the top context does not change when doing callbacks or | 4313 // Make sure that the top context does not change when doing callbacks or |
| 4090 // interceptor calls. | 4314 // interceptor calls. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4112 case EXTERNAL_SHORT_ELEMENTS: | 4336 case EXTERNAL_SHORT_ELEMENTS: |
| 4113 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4337 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 4114 case EXTERNAL_INT_ELEMENTS: | 4338 case EXTERNAL_INT_ELEMENTS: |
| 4115 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4339 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4116 case EXTERNAL_FLOAT_ELEMENTS: | 4340 case EXTERNAL_FLOAT_ELEMENTS: |
| 4117 case EXTERNAL_DOUBLE_ELEMENTS: | 4341 case EXTERNAL_DOUBLE_ELEMENTS: |
| 4118 // Ignore getters and setters on pixel and external array | 4342 // Ignore getters and setters on pixel and external array |
| 4119 // elements. | 4343 // elements. |
| 4120 return heap->undefined_value(); | 4344 return heap->undefined_value(); |
| 4121 case DICTIONARY_ELEMENTS: { | 4345 case DICTIONARY_ELEMENTS: { |
| 4122 Object* probe = | 4346 Object* probe = UpdateGetterSetterInDictionary(element_dictionary(), |
| 4123 FindGetterSetterInDictionary(element_dictionary(), index, heap); | 4347 index, |
| 4348 attributes, |
| 4349 heap); |
| 4124 if (!probe->IsTheHole()) return probe; | 4350 if (!probe->IsTheHole()) return probe; |
| 4125 // Otherwise allow to override it. | 4351 // Otherwise allow to override it. |
| 4126 break; | 4352 break; |
| 4127 } | 4353 } |
| 4128 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 4354 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 4129 // Ascertain whether we have read-only properties or an existing | 4355 // Ascertain whether we have read-only properties or an existing |
| 4130 // getter/setter pair in an arguments elements dictionary backing | 4356 // getter/setter pair in an arguments elements dictionary backing |
| 4131 // store. | 4357 // store. |
| 4132 FixedArray* parameter_map = FixedArray::cast(elements()); | 4358 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 4133 uint32_t length = parameter_map->length(); | 4359 uint32_t length = parameter_map->length(); |
| 4134 Object* probe = | 4360 Object* probe = |
| 4135 index < (length - 2) ? parameter_map->get(index + 2) : NULL; | 4361 index < (length - 2) ? parameter_map->get(index + 2) : NULL; |
| 4136 if (probe == NULL || probe->IsTheHole()) { | 4362 if (probe == NULL || probe->IsTheHole()) { |
| 4137 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 4363 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 4138 if (arguments->IsDictionary()) { | 4364 if (arguments->IsDictionary()) { |
| 4139 NumberDictionary* dictionary = NumberDictionary::cast(arguments); | 4365 NumberDictionary* dictionary = NumberDictionary::cast(arguments); |
| 4140 probe = FindGetterSetterInDictionary(dictionary, index, heap); | 4366 probe = UpdateGetterSetterInDictionary(dictionary, |
| 4367 index, |
| 4368 attributes, |
| 4369 heap); |
| 4141 if (!probe->IsTheHole()) return probe; | 4370 if (!probe->IsTheHole()) return probe; |
| 4142 } | 4371 } |
| 4143 } | 4372 } |
| 4144 break; | 4373 break; |
| 4145 } | 4374 } |
| 4146 } | 4375 } |
| 4147 } else { | 4376 } else { |
| 4148 // Lookup the name. | 4377 // Lookup the name. |
| 4149 LookupResult result; | 4378 LookupResult result(heap->isolate()); |
| 4150 LocalLookup(name, &result); | 4379 LocalLookup(name, &result); |
| 4151 if (result.IsProperty()) { | 4380 if (result.IsProperty()) { |
| 4152 if (result.IsReadOnly()) return heap->undefined_value(); | 4381 if (result.IsReadOnly()) return heap->undefined_value(); |
| 4153 if (result.type() == CALLBACKS) { | 4382 if (result.type() == CALLBACKS) { |
| 4154 Object* obj = result.GetCallbackObject(); | 4383 Object* obj = result.GetCallbackObject(); |
| 4155 // Need to preserve old getters/setters. | 4384 // Need to preserve old getters/setters. |
| 4156 if (obj->IsFixedArray()) { | 4385 if (obj->IsFixedArray()) { |
| 4157 // Use set to update attributes. | 4386 // Use set to update attributes. |
| 4158 return SetPropertyCallback(name, obj, attributes); | 4387 return SetPropertyCallback(name, obj, attributes); |
| 4159 } | 4388 } |
| 4160 } | 4389 } |
| 4161 } | 4390 } |
| 4162 } | 4391 } |
| 4163 | 4392 |
| 4164 // Allocate the fixed array to hold getter and setter. | 4393 // Allocate the fixed array to hold getter and setter. |
| 4165 Object* structure; | 4394 Object* structure; |
| 4166 { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED); | 4395 { MaybeObject* maybe_structure = heap->AllocateFixedArray(2, TENURED); |
| 4167 if (!maybe_structure->ToObject(&structure)) return maybe_structure; | 4396 if (!maybe_structure->ToObject(&structure)) return maybe_structure; |
| 4168 } | 4397 } |
| 4169 | 4398 |
| 4170 if (is_element) { | 4399 if (is_element) { |
| 4171 return SetElementCallback(index, structure, attributes); | 4400 return SetElementCallback(index, structure, attributes); |
| 4172 } else { | 4401 } else { |
| 4173 return SetPropertyCallback(name, structure, attributes); | 4402 return SetPropertyCallback(name, structure, attributes); |
| 4174 } | 4403 } |
| 4175 } | 4404 } |
| 4176 | 4405 |
| 4177 | 4406 |
| 4178 bool JSObject::CanSetCallback(String* name) { | 4407 bool JSObject::CanSetCallback(String* name) { |
| 4179 ASSERT(!IsAccessCheckNeeded() | 4408 ASSERT(!IsAccessCheckNeeded() || |
| 4180 || Isolate::Current()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 4409 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
| 4181 | 4410 |
| 4182 // Check if there is an API defined callback object which prohibits | 4411 // Check if there is an API defined callback object which prohibits |
| 4183 // callback overwriting in this object or it's prototype chain. | 4412 // callback overwriting in this object or it's prototype chain. |
| 4184 // This mechanism is needed for instance in a browser setting, where | 4413 // This mechanism is needed for instance in a browser setting, where |
| 4185 // certain accessors such as window.location should not be allowed | 4414 // certain accessors such as window.location should not be allowed |
| 4186 // to be overwritten because allowing overwriting could potentially | 4415 // to be overwritten because allowing overwriting could potentially |
| 4187 // cause security problems. | 4416 // cause security problems. |
| 4188 LookupResult callback_result; | 4417 LookupResult callback_result(GetIsolate()); |
| 4189 LookupCallback(name, &callback_result); | 4418 LookupCallback(name, &callback_result); |
| 4190 if (callback_result.IsProperty()) { | 4419 if (callback_result.IsProperty()) { |
| 4191 Object* obj = callback_result.GetCallbackObject(); | 4420 Object* obj = callback_result.GetCallbackObject(); |
| 4192 if (obj->IsAccessorInfo() && | 4421 if (obj->IsAccessorInfo() && |
| 4193 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 4422 AccessorInfo::cast(obj)->prohibits_overwriting()) { |
| 4194 return false; | 4423 return false; |
| 4195 } | 4424 } |
| 4196 } | 4425 } |
| 4197 | 4426 |
| 4198 return true; | 4427 return true; |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4375 break; | 4604 break; |
| 4376 } | 4605 } |
| 4377 | 4606 |
| 4378 Object* ok; | 4607 Object* ok; |
| 4379 { MaybeObject* maybe_ok = | 4608 { MaybeObject* maybe_ok = |
| 4380 SetElementCallback(index, info, info->property_attributes()); | 4609 SetElementCallback(index, info, info->property_attributes()); |
| 4381 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 4610 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| 4382 } | 4611 } |
| 4383 } else { | 4612 } else { |
| 4384 // Lookup the name. | 4613 // Lookup the name. |
| 4385 LookupResult result; | 4614 LookupResult result(isolate); |
| 4386 LocalLookup(name, &result); | 4615 LocalLookup(name, &result); |
| 4387 // ES5 forbids turning a property into an accessor if it's not | 4616 // ES5 forbids turning a property into an accessor if it's not |
| 4388 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). | 4617 // configurable (that is IsDontDelete in ES3 and v8), see 8.6.1 (Table 5). |
| 4389 if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { | 4618 if (result.IsProperty() && (result.IsReadOnly() || result.IsDontDelete())) { |
| 4390 return isolate->heap()->undefined_value(); | 4619 return isolate->heap()->undefined_value(); |
| 4391 } | 4620 } |
| 4392 Object* ok; | 4621 Object* ok; |
| 4393 { MaybeObject* maybe_ok = | 4622 { MaybeObject* maybe_ok = |
| 4394 SetPropertyCallback(name, info, info->property_attributes()); | 4623 SetPropertyCallback(name, info, info->property_attributes()); |
| 4395 if (!maybe_ok->ToObject(&ok)) return maybe_ok; | 4624 if (!maybe_ok->ToObject(&ok)) return maybe_ok; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4433 return FixedArray::cast(element)->get(accessor_index); | 4662 return FixedArray::cast(element)->get(accessor_index); |
| 4434 } | 4663 } |
| 4435 } | 4664 } |
| 4436 } | 4665 } |
| 4437 } | 4666 } |
| 4438 } | 4667 } |
| 4439 } else { | 4668 } else { |
| 4440 for (Object* obj = this; | 4669 for (Object* obj = this; |
| 4441 obj != heap->null_value(); | 4670 obj != heap->null_value(); |
| 4442 obj = JSObject::cast(obj)->GetPrototype()) { | 4671 obj = JSObject::cast(obj)->GetPrototype()) { |
| 4443 LookupResult result; | 4672 LookupResult result(heap->isolate()); |
| 4444 JSObject::cast(obj)->LocalLookup(name, &result); | 4673 JSObject::cast(obj)->LocalLookup(name, &result); |
| 4445 if (result.IsProperty()) { | 4674 if (result.IsProperty()) { |
| 4446 if (result.IsReadOnly()) return heap->undefined_value(); | 4675 if (result.IsReadOnly()) return heap->undefined_value(); |
| 4447 if (result.type() == CALLBACKS) { | 4676 if (result.type() == CALLBACKS) { |
| 4448 Object* obj = result.GetCallbackObject(); | 4677 Object* obj = result.GetCallbackObject(); |
| 4449 if (obj->IsFixedArray()) { | 4678 if (obj->IsFixedArray()) { |
| 4450 return FixedArray::cast(obj)->get(accessor_index); | 4679 return FixedArray::cast(obj)->get(accessor_index); |
| 4451 } | 4680 } |
| 4452 } | 4681 } |
| 4453 } | 4682 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4541 Map::cast(result)->set_prototype(prototype()); | 4770 Map::cast(result)->set_prototype(prototype()); |
| 4542 Map::cast(result)->set_constructor(constructor()); | 4771 Map::cast(result)->set_constructor(constructor()); |
| 4543 | 4772 |
| 4544 Map::cast(result)->set_bit_field(bit_field()); | 4773 Map::cast(result)->set_bit_field(bit_field()); |
| 4545 Map::cast(result)->set_bit_field2(bit_field2()); | 4774 Map::cast(result)->set_bit_field2(bit_field2()); |
| 4546 Map::cast(result)->set_bit_field3(bit_field3()); | 4775 Map::cast(result)->set_bit_field3(bit_field3()); |
| 4547 | 4776 |
| 4548 Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP); | 4777 Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP); |
| 4549 | 4778 |
| 4550 #ifdef DEBUG | 4779 #ifdef DEBUG |
| 4551 if (Map::cast(result)->is_shared()) { | 4780 if (FLAG_verify_heap && Map::cast(result)->is_shared()) { |
| 4552 Map::cast(result)->SharedMapVerify(); | 4781 Map::cast(result)->SharedMapVerify(); |
| 4553 } | 4782 } |
| 4554 #endif | 4783 #endif |
| 4555 | 4784 |
| 4556 return result; | 4785 return result; |
| 4557 } | 4786 } |
| 4558 | 4787 |
| 4559 | 4788 |
| 4560 MaybeObject* Map::CopyDropTransitions() { | 4789 MaybeObject* Map::CopyDropTransitions() { |
| 4561 Object* new_map; | 4790 Object* new_map; |
| 4562 { MaybeObject* maybe_new_map = CopyDropDescriptors(); | 4791 { MaybeObject* maybe_new_map = CopyDropDescriptors(); |
| 4563 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 4792 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 4564 } | 4793 } |
| 4565 Object* descriptors; | 4794 Object* descriptors; |
| 4566 { MaybeObject* maybe_descriptors = | 4795 { MaybeObject* maybe_descriptors = |
| 4567 instance_descriptors()->RemoveTransitions(); | 4796 instance_descriptors()->RemoveTransitions(); |
| 4568 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; | 4797 if (!maybe_descriptors->ToObject(&descriptors)) return maybe_descriptors; |
| 4569 } | 4798 } |
| 4570 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); | 4799 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); |
| 4571 return new_map; | 4800 return new_map; |
| 4572 } | 4801 } |
| 4573 | 4802 |
| 4803 void Map::UpdateCodeCache(Handle<Map> map, |
| 4804 Handle<String> name, |
| 4805 Handle<Code> code) { |
| 4806 Isolate* isolate = map->GetIsolate(); |
| 4807 CALL_HEAP_FUNCTION_VOID(isolate, |
| 4808 map->UpdateCodeCache(*name, *code)); |
| 4809 } |
| 4574 | 4810 |
| 4575 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { | 4811 MaybeObject* Map::UpdateCodeCache(String* name, Code* code) { |
| 4576 // Allocate the code cache if not present. | 4812 // Allocate the code cache if not present. |
| 4577 if (code_cache()->IsFixedArray()) { | 4813 if (code_cache()->IsFixedArray()) { |
| 4578 Object* result; | 4814 Object* result; |
| 4579 { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache(); | 4815 { MaybeObject* maybe_result = GetHeap()->AllocateCodeCache(); |
| 4580 if (!maybe_result->ToObject(&result)) return maybe_result; | 4816 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 4581 } | 4817 } |
| 4582 set_code_cache(result); | 4818 set_code_cache(result); |
| 4583 } | 4819 } |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4953 | 5189 |
| 4954 void CodeCacheHashTable::RemoveByIndex(int index) { | 5190 void CodeCacheHashTable::RemoveByIndex(int index) { |
| 4955 ASSERT(index >= 0); | 5191 ASSERT(index >= 0); |
| 4956 Heap* heap = GetHeap(); | 5192 Heap* heap = GetHeap(); |
| 4957 set(EntryToIndex(index), heap->null_value()); | 5193 set(EntryToIndex(index), heap->null_value()); |
| 4958 set(EntryToIndex(index) + 1, heap->null_value()); | 5194 set(EntryToIndex(index) + 1, heap->null_value()); |
| 4959 ElementRemoved(); | 5195 ElementRemoved(); |
| 4960 } | 5196 } |
| 4961 | 5197 |
| 4962 | 5198 |
| 4963 MaybeObject* PolymorphicCodeCache::Update(MapList* maps, | 5199 void PolymorphicCodeCache::Update(Handle<PolymorphicCodeCache> cache, |
| 5200 MapHandleList* maps, |
| 5201 Code::Flags flags, |
| 5202 Handle<Code> code) { |
| 5203 Isolate* isolate = cache->GetIsolate(); |
| 5204 CALL_HEAP_FUNCTION_VOID(isolate, cache->Update(maps, flags, *code)); |
| 5205 } |
| 5206 |
| 5207 |
| 5208 MaybeObject* PolymorphicCodeCache::Update(MapHandleList* maps, |
| 4964 Code::Flags flags, | 5209 Code::Flags flags, |
| 4965 Code* code) { | 5210 Code* code) { |
| 4966 // Initialize cache if necessary. | 5211 // Initialize cache if necessary. |
| 4967 if (cache()->IsUndefined()) { | 5212 if (cache()->IsUndefined()) { |
| 4968 Object* result; | 5213 Object* result; |
| 4969 { MaybeObject* maybe_result = | 5214 { MaybeObject* maybe_result = |
| 4970 PolymorphicCodeCacheHashTable::Allocate( | 5215 PolymorphicCodeCacheHashTable::Allocate( |
| 4971 PolymorphicCodeCacheHashTable::kInitialSize); | 5216 PolymorphicCodeCacheHashTable::kInitialSize); |
| 4972 if (!maybe_result->ToObject(&result)) return maybe_result; | 5217 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 4973 } | 5218 } |
| 4974 set_cache(result); | 5219 set_cache(result); |
| 4975 } else { | 5220 } else { |
| 4976 // This entry shouldn't be contained in the cache yet. | 5221 // This entry shouldn't be contained in the cache yet. |
| 4977 ASSERT(PolymorphicCodeCacheHashTable::cast(cache()) | 5222 ASSERT(PolymorphicCodeCacheHashTable::cast(cache()) |
| 4978 ->Lookup(maps, flags)->IsUndefined()); | 5223 ->Lookup(maps, flags)->IsUndefined()); |
| 4979 } | 5224 } |
| 4980 PolymorphicCodeCacheHashTable* hash_table = | 5225 PolymorphicCodeCacheHashTable* hash_table = |
| 4981 PolymorphicCodeCacheHashTable::cast(cache()); | 5226 PolymorphicCodeCacheHashTable::cast(cache()); |
| 4982 Object* new_cache; | 5227 Object* new_cache; |
| 4983 { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code); | 5228 { MaybeObject* maybe_new_cache = hash_table->Put(maps, flags, code); |
| 4984 if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache; | 5229 if (!maybe_new_cache->ToObject(&new_cache)) return maybe_new_cache; |
| 4985 } | 5230 } |
| 4986 set_cache(new_cache); | 5231 set_cache(new_cache); |
| 4987 return this; | 5232 return this; |
| 4988 } | 5233 } |
| 4989 | 5234 |
| 4990 | 5235 |
| 4991 Object* PolymorphicCodeCache::Lookup(MapList* maps, Code::Flags flags) { | 5236 Handle<Object> PolymorphicCodeCache::Lookup(MapHandleList* maps, |
| 5237 Code::Flags flags) { |
| 4992 if (!cache()->IsUndefined()) { | 5238 if (!cache()->IsUndefined()) { |
| 4993 PolymorphicCodeCacheHashTable* hash_table = | 5239 PolymorphicCodeCacheHashTable* hash_table = |
| 4994 PolymorphicCodeCacheHashTable::cast(cache()); | 5240 PolymorphicCodeCacheHashTable::cast(cache()); |
| 4995 return hash_table->Lookup(maps, flags); | 5241 return Handle<Object>(hash_table->Lookup(maps, flags)); |
| 4996 } else { | 5242 } else { |
| 4997 return GetHeap()->undefined_value(); | 5243 return GetIsolate()->factory()->undefined_value(); |
| 4998 } | 5244 } |
| 4999 } | 5245 } |
| 5000 | 5246 |
| 5001 | 5247 |
| 5002 // Despite their name, object of this class are not stored in the actual | 5248 // Despite their name, object of this class are not stored in the actual |
| 5003 // hash table; instead they're temporarily used for lookups. It is therefore | 5249 // hash table; instead they're temporarily used for lookups. It is therefore |
| 5004 // safe to have a weak (non-owning) pointer to a MapList as a member field. | 5250 // safe to have a weak (non-owning) pointer to a MapList as a member field. |
| 5005 class PolymorphicCodeCacheHashTableKey : public HashTableKey { | 5251 class PolymorphicCodeCacheHashTableKey : public HashTableKey { |
| 5006 public: | 5252 public: |
| 5007 // Callers must ensure that |maps| outlives the newly constructed object. | 5253 // Callers must ensure that |maps| outlives the newly constructed object. |
| 5008 PolymorphicCodeCacheHashTableKey(MapList* maps, int code_flags) | 5254 PolymorphicCodeCacheHashTableKey(MapHandleList* maps, int code_flags) |
| 5009 : maps_(maps), | 5255 : maps_(maps), |
| 5010 code_flags_(code_flags) {} | 5256 code_flags_(code_flags) {} |
| 5011 | 5257 |
| 5012 bool IsMatch(Object* other) { | 5258 bool IsMatch(Object* other) { |
| 5013 MapList other_maps(kDefaultListAllocationSize); | 5259 MapHandleList other_maps(kDefaultListAllocationSize); |
| 5014 int other_flags; | 5260 int other_flags; |
| 5015 FromObject(other, &other_flags, &other_maps); | 5261 FromObject(other, &other_flags, &other_maps); |
| 5016 if (code_flags_ != other_flags) return false; | 5262 if (code_flags_ != other_flags) return false; |
| 5017 if (maps_->length() != other_maps.length()) return false; | 5263 if (maps_->length() != other_maps.length()) return false; |
| 5018 // Compare just the hashes first because it's faster. | 5264 // Compare just the hashes first because it's faster. |
| 5019 int this_hash = MapsHashHelper(maps_, code_flags_); | 5265 int this_hash = MapsHashHelper(maps_, code_flags_); |
| 5020 int other_hash = MapsHashHelper(&other_maps, other_flags); | 5266 int other_hash = MapsHashHelper(&other_maps, other_flags); |
| 5021 if (this_hash != other_hash) return false; | 5267 if (this_hash != other_hash) return false; |
| 5022 | 5268 |
| 5023 // Full comparison: for each map in maps_, look for an equivalent map in | 5269 // Full comparison: for each map in maps_, look for an equivalent map in |
| 5024 // other_maps. This implementation is slow, but probably good enough for | 5270 // other_maps. This implementation is slow, but probably good enough for |
| 5025 // now because the lists are short (<= 4 elements currently). | 5271 // now because the lists are short (<= 4 elements currently). |
| 5026 for (int i = 0; i < maps_->length(); ++i) { | 5272 for (int i = 0; i < maps_->length(); ++i) { |
| 5027 bool match_found = false; | 5273 bool match_found = false; |
| 5028 for (int j = 0; j < other_maps.length(); ++j) { | 5274 for (int j = 0; j < other_maps.length(); ++j) { |
| 5029 if (maps_->at(i)->EquivalentTo(other_maps.at(j))) { | 5275 if (maps_->at(i)->EquivalentTo(*other_maps.at(j))) { |
| 5030 match_found = true; | 5276 match_found = true; |
| 5031 break; | 5277 break; |
| 5032 } | 5278 } |
| 5033 } | 5279 } |
| 5034 if (!match_found) return false; | 5280 if (!match_found) return false; |
| 5035 } | 5281 } |
| 5036 return true; | 5282 return true; |
| 5037 } | 5283 } |
| 5038 | 5284 |
| 5039 static uint32_t MapsHashHelper(MapList* maps, int code_flags) { | 5285 static uint32_t MapsHashHelper(MapHandleList* maps, int code_flags) { |
| 5040 uint32_t hash = code_flags; | 5286 uint32_t hash = code_flags; |
| 5041 for (int i = 0; i < maps->length(); ++i) { | 5287 for (int i = 0; i < maps->length(); ++i) { |
| 5042 hash ^= maps->at(i)->Hash(); | 5288 hash ^= maps->at(i)->Hash(); |
| 5043 } | 5289 } |
| 5044 return hash; | 5290 return hash; |
| 5045 } | 5291 } |
| 5046 | 5292 |
| 5047 uint32_t Hash() { | 5293 uint32_t Hash() { |
| 5048 return MapsHashHelper(maps_, code_flags_); | 5294 return MapsHashHelper(maps_, code_flags_); |
| 5049 } | 5295 } |
| 5050 | 5296 |
| 5051 uint32_t HashForObject(Object* obj) { | 5297 uint32_t HashForObject(Object* obj) { |
| 5052 MapList other_maps(kDefaultListAllocationSize); | 5298 MapHandleList other_maps(kDefaultListAllocationSize); |
| 5053 int other_flags; | 5299 int other_flags; |
| 5054 FromObject(obj, &other_flags, &other_maps); | 5300 FromObject(obj, &other_flags, &other_maps); |
| 5055 return MapsHashHelper(&other_maps, other_flags); | 5301 return MapsHashHelper(&other_maps, other_flags); |
| 5056 } | 5302 } |
| 5057 | 5303 |
| 5058 MUST_USE_RESULT MaybeObject* AsObject() { | 5304 MUST_USE_RESULT MaybeObject* AsObject() { |
| 5059 Object* obj; | 5305 Object* obj; |
| 5060 // The maps in |maps_| must be copied to a newly allocated FixedArray, | 5306 // The maps in |maps_| must be copied to a newly allocated FixedArray, |
| 5061 // both because the referenced MapList is short-lived, and because C++ | 5307 // both because the referenced MapList is short-lived, and because C++ |
| 5062 // objects can't be stored in the heap anyway. | 5308 // objects can't be stored in the heap anyway. |
| 5063 { MaybeObject* maybe_obj = | 5309 { MaybeObject* maybe_obj = |
| 5064 HEAP->AllocateUninitializedFixedArray(maps_->length() + 1); | 5310 HEAP->AllocateUninitializedFixedArray(maps_->length() + 1); |
| 5065 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 5311 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 5066 } | 5312 } |
| 5067 FixedArray* list = FixedArray::cast(obj); | 5313 FixedArray* list = FixedArray::cast(obj); |
| 5068 list->set(0, Smi::FromInt(code_flags_)); | 5314 list->set(0, Smi::FromInt(code_flags_)); |
| 5069 for (int i = 0; i < maps_->length(); ++i) { | 5315 for (int i = 0; i < maps_->length(); ++i) { |
| 5070 list->set(i + 1, maps_->at(i)); | 5316 list->set(i + 1, *maps_->at(i)); |
| 5071 } | 5317 } |
| 5072 return list; | 5318 return list; |
| 5073 } | 5319 } |
| 5074 | 5320 |
| 5075 private: | 5321 private: |
| 5076 static MapList* FromObject(Object* obj, int* code_flags, MapList* maps) { | 5322 static MapHandleList* FromObject(Object* obj, |
| 5323 int* code_flags, |
| 5324 MapHandleList* maps) { |
| 5077 FixedArray* list = FixedArray::cast(obj); | 5325 FixedArray* list = FixedArray::cast(obj); |
| 5078 maps->Rewind(0); | 5326 maps->Rewind(0); |
| 5079 *code_flags = Smi::cast(list->get(0))->value(); | 5327 *code_flags = Smi::cast(list->get(0))->value(); |
| 5080 for (int i = 1; i < list->length(); ++i) { | 5328 for (int i = 1; i < list->length(); ++i) { |
| 5081 maps->Add(Map::cast(list->get(i))); | 5329 maps->Add(Handle<Map>(Map::cast(list->get(i)))); |
| 5082 } | 5330 } |
| 5083 return maps; | 5331 return maps; |
| 5084 } | 5332 } |
| 5085 | 5333 |
| 5086 MapList* maps_; // weak. | 5334 MapHandleList* maps_; // weak. |
| 5087 int code_flags_; | 5335 int code_flags_; |
| 5088 static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1; | 5336 static const int kDefaultListAllocationSize = kMaxKeyedPolymorphism + 1; |
| 5089 }; | 5337 }; |
| 5090 | 5338 |
| 5091 | 5339 |
| 5092 Object* PolymorphicCodeCacheHashTable::Lookup(MapList* maps, int code_flags) { | 5340 Object* PolymorphicCodeCacheHashTable::Lookup(MapHandleList* maps, |
| 5341 int code_flags) { |
| 5093 PolymorphicCodeCacheHashTableKey key(maps, code_flags); | 5342 PolymorphicCodeCacheHashTableKey key(maps, code_flags); |
| 5094 int entry = FindEntry(&key); | 5343 int entry = FindEntry(&key); |
| 5095 if (entry == kNotFound) return GetHeap()->undefined_value(); | 5344 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 5096 return get(EntryToIndex(entry) + 1); | 5345 return get(EntryToIndex(entry) + 1); |
| 5097 } | 5346 } |
| 5098 | 5347 |
| 5099 | 5348 |
| 5100 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapList* maps, | 5349 MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps, |
| 5101 int code_flags, | 5350 int code_flags, |
| 5102 Code* code) { | 5351 Code* code) { |
| 5103 PolymorphicCodeCacheHashTableKey key(maps, code_flags); | 5352 PolymorphicCodeCacheHashTableKey key(maps, code_flags); |
| 5104 Object* obj; | 5353 Object* obj; |
| 5105 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 5354 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 5106 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 5355 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 5107 } | 5356 } |
| 5108 PolymorphicCodeCacheHashTable* cache = | 5357 PolymorphicCodeCacheHashTable* cache = |
| 5109 reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj); | 5358 reinterpret_cast<PolymorphicCodeCacheHashTable*>(obj); |
| 5110 int entry = cache->FindInsertionEntry(key.Hash()); | 5359 int entry = cache->FindInsertionEntry(key.Hash()); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5225 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, | 5474 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
| 5226 FixedArray* new_cache) { | 5475 FixedArray* new_cache) { |
| 5227 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); | 5476 ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); |
| 5228 if (HasEnumCache()) { | 5477 if (HasEnumCache()) { |
| 5229 FixedArray::cast(get(kEnumerationIndexIndex))-> | 5478 FixedArray::cast(get(kEnumerationIndexIndex))-> |
| 5230 set(kEnumCacheBridgeCacheIndex, new_cache); | 5479 set(kEnumCacheBridgeCacheIndex, new_cache); |
| 5231 } else { | 5480 } else { |
| 5232 if (IsEmpty()) return; // Do nothing for empty descriptor array. | 5481 if (IsEmpty()) return; // Do nothing for empty descriptor array. |
| 5233 FixedArray::cast(bridge_storage)-> | 5482 FixedArray::cast(bridge_storage)-> |
| 5234 set(kEnumCacheBridgeCacheIndex, new_cache); | 5483 set(kEnumCacheBridgeCacheIndex, new_cache); |
| 5235 fast_set(FixedArray::cast(bridge_storage), | 5484 NoWriteBarrierSet(FixedArray::cast(bridge_storage), |
| 5236 kEnumCacheBridgeEnumIndex, | 5485 kEnumCacheBridgeEnumIndex, |
| 5237 get(kEnumerationIndexIndex)); | 5486 get(kEnumerationIndexIndex)); |
| 5238 set(kEnumerationIndexIndex, bridge_storage); | 5487 set(kEnumerationIndexIndex, bridge_storage); |
| 5239 } | 5488 } |
| 5240 } | 5489 } |
| 5241 | 5490 |
| 5242 | 5491 |
| 5243 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor, | 5492 MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor, |
| 5244 TransitionFlag transition_flag) { | 5493 TransitionFlag transition_flag) { |
| 5245 // Transitions are only kept when inserting another transition. | 5494 // Transitions are only kept when inserting another transition. |
| 5246 // This precondition is not required by this function's implementation, but | 5495 // This precondition is not required by this function's implementation, but |
| 5247 // is currently required by the semantics of maps, so we check it. | 5496 // is currently required by the semantics of maps, so we check it. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5288 t == FIELD || | 5537 t == FIELD || |
| 5289 t == CALLBACKS || | 5538 t == CALLBACKS || |
| 5290 t == INTERCEPTOR) { | 5539 t == INTERCEPTOR) { |
| 5291 keep_enumeration_index = true; | 5540 keep_enumeration_index = true; |
| 5292 } else if (remove_transitions) { | 5541 } else if (remove_transitions) { |
| 5293 // Replaced descriptor has been counted as removed if it is | 5542 // Replaced descriptor has been counted as removed if it is |
| 5294 // a transition that will be replaced. Adjust count in this case. | 5543 // a transition that will be replaced. Adjust count in this case. |
| 5295 ++new_size; | 5544 ++new_size; |
| 5296 } | 5545 } |
| 5297 } | 5546 } |
| 5547 |
| 5548 DescriptorArray* new_descriptors; |
| 5298 { MaybeObject* maybe_result = Allocate(new_size); | 5549 { MaybeObject* maybe_result = Allocate(new_size); |
| 5299 if (!maybe_result->ToObject(&result)) return maybe_result; | 5550 if (!maybe_result->To<DescriptorArray>(&new_descriptors)) { |
| 5551 return maybe_result; |
| 5552 } |
| 5300 } | 5553 } |
| 5301 DescriptorArray* new_descriptors = DescriptorArray::cast(result); | 5554 |
| 5555 DescriptorArray::WhitenessWitness witness(new_descriptors); |
| 5556 |
| 5302 // Set the enumeration index in the descriptors and set the enumeration index | 5557 // Set the enumeration index in the descriptors and set the enumeration index |
| 5303 // in the result. | 5558 // in the result. |
| 5304 int enumeration_index = NextEnumerationIndex(); | 5559 int enumeration_index = NextEnumerationIndex(); |
| 5305 if (!descriptor->GetDetails().IsTransition()) { | 5560 if (!descriptor->GetDetails().IsTransition()) { |
| 5306 if (keep_enumeration_index) { | 5561 if (keep_enumeration_index) { |
| 5307 descriptor->SetEnumerationIndex( | 5562 descriptor->SetEnumerationIndex( |
| 5308 PropertyDetails(GetDetails(index)).index()); | 5563 PropertyDetails(GetDetails(index)).index()); |
| 5309 } else { | 5564 } else { |
| 5310 descriptor->SetEnumerationIndex(enumeration_index); | 5565 descriptor->SetEnumerationIndex(enumeration_index); |
| 5311 ++enumeration_index; | 5566 ++enumeration_index; |
| 5312 } | 5567 } |
| 5313 } | 5568 } |
| 5314 new_descriptors->SetNextEnumerationIndex(enumeration_index); | 5569 new_descriptors->SetNextEnumerationIndex(enumeration_index); |
| 5315 | 5570 |
| 5316 // Copy the descriptors, filtering out transitions and null descriptors, | 5571 // Copy the descriptors, filtering out transitions and null descriptors, |
| 5317 // and inserting or replacing a descriptor. | 5572 // and inserting or replacing a descriptor. |
| 5318 uint32_t descriptor_hash = descriptor->GetKey()->Hash(); | 5573 uint32_t descriptor_hash = descriptor->GetKey()->Hash(); |
| 5319 int from_index = 0; | 5574 int from_index = 0; |
| 5320 int to_index = 0; | 5575 int to_index = 0; |
| 5321 | 5576 |
| 5322 for (; from_index < number_of_descriptors(); from_index++) { | 5577 for (; from_index < number_of_descriptors(); from_index++) { |
| 5323 String* key = GetKey(from_index); | 5578 String* key = GetKey(from_index); |
| 5324 if (key->Hash() > descriptor_hash || key == descriptor->GetKey()) { | 5579 if (key->Hash() > descriptor_hash || key == descriptor->GetKey()) { |
| 5325 break; | 5580 break; |
| 5326 } | 5581 } |
| 5327 if (IsNullDescriptor(from_index)) continue; | 5582 if (IsNullDescriptor(from_index)) continue; |
| 5328 if (remove_transitions && IsTransition(from_index)) continue; | 5583 if (remove_transitions && IsTransition(from_index)) continue; |
| 5329 new_descriptors->CopyFrom(to_index++, this, from_index); | 5584 new_descriptors->CopyFrom(to_index++, this, from_index, witness); |
| 5330 } | 5585 } |
| 5331 | 5586 |
| 5332 new_descriptors->Set(to_index++, descriptor); | 5587 new_descriptors->Set(to_index++, descriptor, witness); |
| 5333 if (replacing) from_index++; | 5588 if (replacing) from_index++; |
| 5334 | 5589 |
| 5335 for (; from_index < number_of_descriptors(); from_index++) { | 5590 for (; from_index < number_of_descriptors(); from_index++) { |
| 5336 if (IsNullDescriptor(from_index)) continue; | 5591 if (IsNullDescriptor(from_index)) continue; |
| 5337 if (remove_transitions && IsTransition(from_index)) continue; | 5592 if (remove_transitions && IsTransition(from_index)) continue; |
| 5338 new_descriptors->CopyFrom(to_index++, this, from_index); | 5593 new_descriptors->CopyFrom(to_index++, this, from_index, witness); |
| 5339 } | 5594 } |
| 5340 | 5595 |
| 5341 ASSERT(to_index == new_descriptors->number_of_descriptors()); | 5596 ASSERT(to_index == new_descriptors->number_of_descriptors()); |
| 5342 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); | 5597 SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); |
| 5343 | 5598 |
| 5344 return new_descriptors; | 5599 return new_descriptors; |
| 5345 } | 5600 } |
| 5346 | 5601 |
| 5347 | 5602 |
| 5348 MaybeObject* DescriptorArray::RemoveTransitions() { | 5603 MaybeObject* DescriptorArray::RemoveTransitions() { |
| 5349 // Remove all transitions and null descriptors. Return a copy of the array | 5604 // Remove all transitions and null descriptors. Return a copy of the array |
| 5350 // with all transitions removed, or a Failure object if the new array could | 5605 // with all transitions removed, or a Failure object if the new array could |
| 5351 // not be allocated. | 5606 // not be allocated. |
| 5352 | 5607 |
| 5353 // Compute the size of the map transition entries to be removed. | 5608 // Compute the size of the map transition entries to be removed. |
| 5354 int num_removed = 0; | 5609 int num_removed = 0; |
| 5355 for (int i = 0; i < number_of_descriptors(); i++) { | 5610 for (int i = 0; i < number_of_descriptors(); i++) { |
| 5356 if (!IsProperty(i)) num_removed++; | 5611 if (!IsProperty(i)) num_removed++; |
| 5357 } | 5612 } |
| 5358 | 5613 |
| 5359 // Allocate the new descriptor array. | 5614 // Allocate the new descriptor array. |
| 5360 Object* result; | 5615 DescriptorArray* new_descriptors; |
| 5361 { MaybeObject* maybe_result = Allocate(number_of_descriptors() - num_removed); | 5616 { MaybeObject* maybe_result = Allocate(number_of_descriptors() - num_removed); |
| 5362 if (!maybe_result->ToObject(&result)) return maybe_result; | 5617 if (!maybe_result->To<DescriptorArray>(&new_descriptors)) { |
| 5618 return maybe_result; |
| 5619 } |
| 5363 } | 5620 } |
| 5364 DescriptorArray* new_descriptors = DescriptorArray::cast(result); | 5621 |
| 5622 DescriptorArray::WhitenessWitness witness(new_descriptors); |
| 5365 | 5623 |
| 5366 // Copy the content. | 5624 // Copy the content. |
| 5367 int next_descriptor = 0; | 5625 int next_descriptor = 0; |
| 5368 for (int i = 0; i < number_of_descriptors(); i++) { | 5626 for (int i = 0; i < number_of_descriptors(); i++) { |
| 5369 if (IsProperty(i)) new_descriptors->CopyFrom(next_descriptor++, this, i); | 5627 if (IsProperty(i)) { |
| 5628 new_descriptors->CopyFrom(next_descriptor++, this, i, witness); |
| 5629 } |
| 5370 } | 5630 } |
| 5371 ASSERT(next_descriptor == new_descriptors->number_of_descriptors()); | 5631 ASSERT(next_descriptor == new_descriptors->number_of_descriptors()); |
| 5372 | 5632 |
| 5373 return new_descriptors; | 5633 return new_descriptors; |
| 5374 } | 5634 } |
| 5375 | 5635 |
| 5376 | 5636 |
| 5377 void DescriptorArray::SortUnchecked() { | 5637 void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { |
| 5378 // In-place heap sort. | 5638 // In-place heap sort. |
| 5379 int len = number_of_descriptors(); | 5639 int len = number_of_descriptors(); |
| 5380 | 5640 |
| 5381 // Bottom-up max-heap construction. | 5641 // Bottom-up max-heap construction. |
| 5382 // Index of the last node with children | 5642 // Index of the last node with children |
| 5383 const int max_parent_index = (len / 2) - 1; | 5643 const int max_parent_index = (len / 2) - 1; |
| 5384 for (int i = max_parent_index; i >= 0; --i) { | 5644 for (int i = max_parent_index; i >= 0; --i) { |
| 5385 int parent_index = i; | 5645 int parent_index = i; |
| 5386 const uint32_t parent_hash = GetKey(i)->Hash(); | 5646 const uint32_t parent_hash = GetKey(i)->Hash(); |
| 5387 while (parent_index <= max_parent_index) { | 5647 while (parent_index <= max_parent_index) { |
| 5388 int child_index = 2 * parent_index + 1; | 5648 int child_index = 2 * parent_index + 1; |
| 5389 uint32_t child_hash = GetKey(child_index)->Hash(); | 5649 uint32_t child_hash = GetKey(child_index)->Hash(); |
| 5390 if (child_index + 1 < len) { | 5650 if (child_index + 1 < len) { |
| 5391 uint32_t right_child_hash = GetKey(child_index + 1)->Hash(); | 5651 uint32_t right_child_hash = GetKey(child_index + 1)->Hash(); |
| 5392 if (right_child_hash > child_hash) { | 5652 if (right_child_hash > child_hash) { |
| 5393 child_index++; | 5653 child_index++; |
| 5394 child_hash = right_child_hash; | 5654 child_hash = right_child_hash; |
| 5395 } | 5655 } |
| 5396 } | 5656 } |
| 5397 if (child_hash <= parent_hash) break; | 5657 if (child_hash <= parent_hash) break; |
| 5398 Swap(parent_index, child_index); | 5658 NoWriteBarrierSwapDescriptors(parent_index, child_index); |
| 5399 // Now element at child_index could be < its children. | 5659 // Now element at child_index could be < its children. |
| 5400 parent_index = child_index; // parent_hash remains correct. | 5660 parent_index = child_index; // parent_hash remains correct. |
| 5401 } | 5661 } |
| 5402 } | 5662 } |
| 5403 | 5663 |
| 5404 // Extract elements and create sorted array. | 5664 // Extract elements and create sorted array. |
| 5405 for (int i = len - 1; i > 0; --i) { | 5665 for (int i = len - 1; i > 0; --i) { |
| 5406 // Put max element at the back of the array. | 5666 // Put max element at the back of the array. |
| 5407 Swap(0, i); | 5667 NoWriteBarrierSwapDescriptors(0, i); |
| 5408 // Sift down the new top element. | 5668 // Shift down the new top element. |
| 5409 int parent_index = 0; | 5669 int parent_index = 0; |
| 5410 const uint32_t parent_hash = GetKey(parent_index)->Hash(); | 5670 const uint32_t parent_hash = GetKey(parent_index)->Hash(); |
| 5411 const int max_parent_index = (i / 2) - 1; | 5671 const int max_parent_index = (i / 2) - 1; |
| 5412 while (parent_index <= max_parent_index) { | 5672 while (parent_index <= max_parent_index) { |
| 5413 int child_index = parent_index * 2 + 1; | 5673 int child_index = parent_index * 2 + 1; |
| 5414 uint32_t child_hash = GetKey(child_index)->Hash(); | 5674 uint32_t child_hash = GetKey(child_index)->Hash(); |
| 5415 if (child_index + 1 < i) { | 5675 if (child_index + 1 < i) { |
| 5416 uint32_t right_child_hash = GetKey(child_index + 1)->Hash(); | 5676 uint32_t right_child_hash = GetKey(child_index + 1)->Hash(); |
| 5417 if (right_child_hash > child_hash) { | 5677 if (right_child_hash > child_hash) { |
| 5418 child_index++; | 5678 child_index++; |
| 5419 child_hash = right_child_hash; | 5679 child_hash = right_child_hash; |
| 5420 } | 5680 } |
| 5421 } | 5681 } |
| 5422 if (child_hash <= parent_hash) break; | 5682 if (child_hash <= parent_hash) break; |
| 5423 Swap(parent_index, child_index); | 5683 NoWriteBarrierSwapDescriptors(parent_index, child_index); |
| 5424 parent_index = child_index; | 5684 parent_index = child_index; |
| 5425 } | 5685 } |
| 5426 } | 5686 } |
| 5427 } | 5687 } |
| 5428 | 5688 |
| 5429 | 5689 |
| 5430 void DescriptorArray::Sort() { | 5690 void DescriptorArray::Sort(const WhitenessWitness& witness) { |
| 5431 SortUnchecked(); | 5691 SortUnchecked(witness); |
| 5432 SLOW_ASSERT(IsSortedNoDuplicates()); | 5692 SLOW_ASSERT(IsSortedNoDuplicates()); |
| 5433 } | 5693 } |
| 5434 | 5694 |
| 5435 | 5695 |
| 5436 int DescriptorArray::BinarySearch(String* name, int low, int high) { | 5696 int DescriptorArray::BinarySearch(String* name, int low, int high) { |
| 5437 uint32_t hash = name->Hash(); | 5697 uint32_t hash = name->Hash(); |
| 5438 | 5698 |
| 5439 while (low <= high) { | 5699 while (low <= high) { |
| 5440 int mid = (low + high) / 2; | 5700 int mid = (low + high) / 2; |
| 5441 String* mid_name = GetKey(mid); | 5701 String* mid_name = GetKey(mid); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5506 } | 5766 } |
| 5507 #endif | 5767 #endif |
| 5508 | 5768 |
| 5509 | 5769 |
| 5510 bool String::LooksValid() { | 5770 bool String::LooksValid() { |
| 5511 if (!Isolate::Current()->heap()->Contains(this)) return false; | 5771 if (!Isolate::Current()->heap()->Contains(this)) return false; |
| 5512 return true; | 5772 return true; |
| 5513 } | 5773 } |
| 5514 | 5774 |
| 5515 | 5775 |
| 5516 int String::Utf8Length() { | |
| 5517 if (IsAsciiRepresentation()) return length(); | |
| 5518 // Attempt to flatten before accessing the string. It probably | |
| 5519 // doesn't make Utf8Length faster, but it is very likely that | |
| 5520 // the string will be accessed later (for example by WriteUtf8) | |
| 5521 // so it's still a good idea. | |
| 5522 Heap* heap = GetHeap(); | |
| 5523 TryFlatten(); | |
| 5524 Access<StringInputBuffer> buffer( | |
| 5525 heap->isolate()->objects_string_input_buffer()); | |
| 5526 buffer->Reset(0, this); | |
| 5527 int result = 0; | |
| 5528 while (buffer->has_more()) | |
| 5529 result += unibrow::Utf8::Length(buffer->GetNext()); | |
| 5530 return result; | |
| 5531 } | |
| 5532 | |
| 5533 | |
| 5534 String::FlatContent String::GetFlatContent() { | 5776 String::FlatContent String::GetFlatContent() { |
| 5535 int length = this->length(); | 5777 int length = this->length(); |
| 5536 StringShape shape(this); | 5778 StringShape shape(this); |
| 5537 String* string = this; | 5779 String* string = this; |
| 5538 int offset = 0; | 5780 int offset = 0; |
| 5539 if (shape.representation_tag() == kConsStringTag) { | 5781 if (shape.representation_tag() == kConsStringTag) { |
| 5540 ConsString* cons = ConsString::cast(string); | 5782 ConsString* cons = ConsString::cast(string); |
| 5541 if (cons->second()->length() != 0) { | 5783 if (cons->second()->length() != 0) { |
| 5542 return FlatContent(); | 5784 return FlatContent(); |
| 5543 } | 5785 } |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5947 max_chars); | 6189 max_chars); |
| 5948 default: | 6190 default: |
| 5949 break; | 6191 break; |
| 5950 } | 6192 } |
| 5951 | 6193 |
| 5952 UNREACHABLE(); | 6194 UNREACHABLE(); |
| 5953 return 0; | 6195 return 0; |
| 5954 } | 6196 } |
| 5955 | 6197 |
| 5956 | 6198 |
| 6199 // This method determines the type of string involved and then gets the UTF8 |
| 6200 // length of the string. It doesn't flatten the string and has log(n) recursion |
| 6201 // for a string of length n. |
| 6202 int String::Utf8Length(String* input, int from, int to) { |
| 6203 if (from == to) return 0; |
| 6204 int total = 0; |
| 6205 while (true) { |
| 6206 if (input->IsAsciiRepresentation()) return total + to - from; |
| 6207 switch (StringShape(input).representation_tag()) { |
| 6208 case kConsStringTag: { |
| 6209 ConsString* str = ConsString::cast(input); |
| 6210 String* first = str->first(); |
| 6211 String* second = str->second(); |
| 6212 int first_length = first->length(); |
| 6213 if (first_length - from < to - first_length) { |
| 6214 if (first_length > from) { |
| 6215 // Left hand side is shorter. |
| 6216 total += Utf8Length(first, from, first_length); |
| 6217 input = second; |
| 6218 from = 0; |
| 6219 to -= first_length; |
| 6220 } else { |
| 6221 // We only need the right hand side. |
| 6222 input = second; |
| 6223 from -= first_length; |
| 6224 to -= first_length; |
| 6225 } |
| 6226 } else { |
| 6227 if (first_length <= to) { |
| 6228 // Right hand side is shorter. |
| 6229 total += Utf8Length(second, 0, to - first_length); |
| 6230 input = first; |
| 6231 to = first_length; |
| 6232 } else { |
| 6233 // We only need the left hand side. |
| 6234 input = first; |
| 6235 } |
| 6236 } |
| 6237 continue; |
| 6238 } |
| 6239 case kExternalStringTag: |
| 6240 case kSeqStringTag: { |
| 6241 Vector<const uc16> vector = input->GetFlatContent().ToUC16Vector(); |
| 6242 const uc16* p = vector.start(); |
| 6243 for (int i = from; i < to; i++) { |
| 6244 total += unibrow::Utf8::Length(p[i]); |
| 6245 } |
| 6246 return total; |
| 6247 } |
| 6248 case kSlicedStringTag: { |
| 6249 SlicedString* str = SlicedString::cast(input); |
| 6250 int offset = str->offset(); |
| 6251 input = str->parent(); |
| 6252 from += offset; |
| 6253 to += offset; |
| 6254 continue; |
| 6255 } |
| 6256 default: |
| 6257 break; |
| 6258 } |
| 6259 UNREACHABLE(); |
| 6260 return 0; |
| 6261 } |
| 6262 return 0; |
| 6263 } |
| 6264 |
| 6265 |
| 5957 void Relocatable::PostGarbageCollectionProcessing() { | 6266 void Relocatable::PostGarbageCollectionProcessing() { |
| 5958 Isolate* isolate = Isolate::Current(); | 6267 Isolate* isolate = Isolate::Current(); |
| 5959 Relocatable* current = isolate->relocatable_top(); | 6268 Relocatable* current = isolate->relocatable_top(); |
| 5960 while (current != NULL) { | 6269 while (current != NULL) { |
| 5961 current->PostGarbageCollection(); | 6270 current->PostGarbageCollection(); |
| 5962 current = current->prev_; | 6271 current = current->prev_; |
| 5963 } | 6272 } |
| 5964 } | 6273 } |
| 5965 | 6274 |
| 5966 | 6275 |
| (...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6844 | 7153 |
| 6845 void JSFunction::MarkForLazyRecompilation() { | 7154 void JSFunction::MarkForLazyRecompilation() { |
| 6846 ASSERT(is_compiled() && !IsOptimized()); | 7155 ASSERT(is_compiled() && !IsOptimized()); |
| 6847 ASSERT(shared()->allows_lazy_compilation() || | 7156 ASSERT(shared()->allows_lazy_compilation() || |
| 6848 code()->optimizable()); | 7157 code()->optimizable()); |
| 6849 Builtins* builtins = GetIsolate()->builtins(); | 7158 Builtins* builtins = GetIsolate()->builtins(); |
| 6850 ReplaceCode(builtins->builtin(Builtins::kLazyRecompile)); | 7159 ReplaceCode(builtins->builtin(Builtins::kLazyRecompile)); |
| 6851 } | 7160 } |
| 6852 | 7161 |
| 6853 | 7162 |
| 7163 bool SharedFunctionInfo::EnsureCompiled(Handle<SharedFunctionInfo> shared, |
| 7164 ClearExceptionFlag flag) { |
| 7165 return shared->is_compiled() || CompileLazy(shared, flag); |
| 7166 } |
| 7167 |
| 7168 |
| 7169 static bool CompileLazyHelper(CompilationInfo* info, |
| 7170 ClearExceptionFlag flag) { |
| 7171 // Compile the source information to a code object. |
| 7172 ASSERT(info->IsOptimizing() || !info->shared_info()->is_compiled()); |
| 7173 ASSERT(!info->isolate()->has_pending_exception()); |
| 7174 bool result = Compiler::CompileLazy(info); |
| 7175 ASSERT(result != Isolate::Current()->has_pending_exception()); |
| 7176 if (!result && flag == CLEAR_EXCEPTION) { |
| 7177 info->isolate()->clear_pending_exception(); |
| 7178 } |
| 7179 return result; |
| 7180 } |
| 7181 |
| 7182 |
| 7183 bool SharedFunctionInfo::CompileLazy(Handle<SharedFunctionInfo> shared, |
| 7184 ClearExceptionFlag flag) { |
| 7185 CompilationInfo info(shared); |
| 7186 return CompileLazyHelper(&info, flag); |
| 7187 } |
| 7188 |
| 7189 |
| 7190 bool JSFunction::CompileLazy(Handle<JSFunction> function, |
| 7191 ClearExceptionFlag flag) { |
| 7192 bool result = true; |
| 7193 if (function->shared()->is_compiled()) { |
| 7194 function->ReplaceCode(function->shared()->code()); |
| 7195 function->shared()->set_code_age(0); |
| 7196 } else { |
| 7197 CompilationInfo info(function); |
| 7198 result = CompileLazyHelper(&info, flag); |
| 7199 ASSERT(!result || function->is_compiled()); |
| 7200 } |
| 7201 return result; |
| 7202 } |
| 7203 |
| 7204 |
| 7205 bool JSFunction::CompileOptimized(Handle<JSFunction> function, |
| 7206 int osr_ast_id, |
| 7207 ClearExceptionFlag flag) { |
| 7208 CompilationInfo info(function); |
| 7209 info.SetOptimizing(osr_ast_id); |
| 7210 return CompileLazyHelper(&info, flag); |
| 7211 } |
| 7212 |
| 7213 |
| 6854 bool JSFunction::IsInlineable() { | 7214 bool JSFunction::IsInlineable() { |
| 6855 if (IsBuiltin()) return false; | 7215 if (IsBuiltin()) return false; |
| 6856 SharedFunctionInfo* shared_info = shared(); | 7216 SharedFunctionInfo* shared_info = shared(); |
| 6857 // Check that the function has a script associated with it. | 7217 // Check that the function has a script associated with it. |
| 6858 if (!shared_info->script()->IsScript()) return false; | 7218 if (!shared_info->script()->IsScript()) return false; |
| 6859 if (shared_info->optimization_disabled()) return false; | 7219 if (shared_info->optimization_disabled()) return false; |
| 6860 Code* code = shared_info->code(); | 7220 Code* code = shared_info->code(); |
| 6861 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; | 7221 if (code->kind() == Code::OPTIMIZED_FUNCTION) return true; |
| 6862 // If we never ran this (unlikely) then lets try to optimize it. | 7222 // If we never ran this (unlikely) then lets try to optimize it. |
| 6863 if (code->kind() != Code::FUNCTION) return true; | 7223 if (code->kind() != Code::FUNCTION) return true; |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7026 | 7386 |
| 7027 Heap* heap = GetHeap(); | 7387 Heap* heap = GetHeap(); |
| 7028 | 7388 |
| 7029 // Traverse the proposed prototype chain looking for setters for properties of | 7389 // Traverse the proposed prototype chain looking for setters for properties of |
| 7030 // the same names as are set by the inline constructor. | 7390 // the same names as are set by the inline constructor. |
| 7031 for (Object* obj = prototype; | 7391 for (Object* obj = prototype; |
| 7032 obj != heap->null_value(); | 7392 obj != heap->null_value(); |
| 7033 obj = obj->GetPrototype()) { | 7393 obj = obj->GetPrototype()) { |
| 7034 JSObject* js_object = JSObject::cast(obj); | 7394 JSObject* js_object = JSObject::cast(obj); |
| 7035 for (int i = 0; i < this_property_assignments_count(); i++) { | 7395 for (int i = 0; i < this_property_assignments_count(); i++) { |
| 7036 LookupResult result; | 7396 LookupResult result(heap->isolate()); |
| 7037 String* name = GetThisPropertyAssignmentName(i); | 7397 String* name = GetThisPropertyAssignmentName(i); |
| 7038 js_object->LocalLookupRealNamedProperty(name, &result); | 7398 js_object->LocalLookupRealNamedProperty(name, &result); |
| 7039 if (result.IsProperty() && result.type() == CALLBACKS) { | 7399 if (result.IsProperty() && result.type() == CALLBACKS) { |
| 7040 return false; | 7400 return false; |
| 7041 } | 7401 } |
| 7042 } | 7402 } |
| 7043 } | 7403 } |
| 7044 | 7404 |
| 7045 return true; | 7405 return true; |
| 7046 } | 7406 } |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7384 | 7744 |
| 7385 void Code::Relocate(intptr_t delta) { | 7745 void Code::Relocate(intptr_t delta) { |
| 7386 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { | 7746 for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) { |
| 7387 it.rinfo()->apply(delta); | 7747 it.rinfo()->apply(delta); |
| 7388 } | 7748 } |
| 7389 CPU::FlushICache(instruction_start(), instruction_size()); | 7749 CPU::FlushICache(instruction_start(), instruction_size()); |
| 7390 } | 7750 } |
| 7391 | 7751 |
| 7392 | 7752 |
| 7393 void Code::CopyFrom(const CodeDesc& desc) { | 7753 void Code::CopyFrom(const CodeDesc& desc) { |
| 7754 ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT); |
| 7755 |
| 7394 // copy code | 7756 // copy code |
| 7395 memmove(instruction_start(), desc.buffer, desc.instr_size); | 7757 memmove(instruction_start(), desc.buffer, desc.instr_size); |
| 7396 | 7758 |
| 7397 // copy reloc info | 7759 // copy reloc info |
| 7398 memmove(relocation_start(), | 7760 memmove(relocation_start(), |
| 7399 desc.buffer + desc.buffer_size - desc.reloc_size, | 7761 desc.buffer + desc.buffer_size - desc.reloc_size, |
| 7400 desc.reloc_size); | 7762 desc.reloc_size); |
| 7401 | 7763 |
| 7402 // unbox handles and relocate | 7764 // unbox handles and relocate |
| 7403 intptr_t delta = instruction_start() - desc.buffer; | 7765 intptr_t delta = instruction_start() - desc.buffer; |
| 7404 int mode_mask = RelocInfo::kCodeTargetMask | | 7766 int mode_mask = RelocInfo::kCodeTargetMask | |
| 7405 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | | 7767 RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) | |
| 7406 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | | 7768 RelocInfo::ModeMask(RelocInfo::GLOBAL_PROPERTY_CELL) | |
| 7407 RelocInfo::kApplyMask; | 7769 RelocInfo::kApplyMask; |
| 7408 Assembler* origin = desc.origin; // Needed to find target_object on X64. | 7770 Assembler* origin = desc.origin; // Needed to find target_object on X64. |
| 7409 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { | 7771 for (RelocIterator it(this, mode_mask); !it.done(); it.next()) { |
| 7410 RelocInfo::Mode mode = it.rinfo()->rmode(); | 7772 RelocInfo::Mode mode = it.rinfo()->rmode(); |
| 7411 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 7773 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
| 7412 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 7774 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 7413 it.rinfo()->set_target_object(*p); | 7775 it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER); |
| 7414 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { | 7776 } else if (mode == RelocInfo::GLOBAL_PROPERTY_CELL) { |
| 7415 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle(); | 7777 Handle<JSGlobalPropertyCell> cell = it.rinfo()->target_cell_handle(); |
| 7416 it.rinfo()->set_target_cell(*cell); | 7778 it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER); |
| 7417 } else if (RelocInfo::IsCodeTarget(mode)) { | 7779 } else if (RelocInfo::IsCodeTarget(mode)) { |
| 7418 // rewrite code handles in inline cache targets to direct | 7780 // rewrite code handles in inline cache targets to direct |
| 7419 // pointers to the first instruction in the code object | 7781 // pointers to the first instruction in the code object |
| 7420 Handle<Object> p = it.rinfo()->target_object_handle(origin); | 7782 Handle<Object> p = it.rinfo()->target_object_handle(origin); |
| 7421 Code* code = Code::cast(*p); | 7783 Code* code = Code::cast(*p); |
| 7422 it.rinfo()->set_target_address(code->instruction_start()); | 7784 it.rinfo()->set_target_address(code->instruction_start(), |
| 7785 SKIP_WRITE_BARRIER); |
| 7423 } else { | 7786 } else { |
| 7424 it.rinfo()->apply(delta); | 7787 it.rinfo()->apply(delta); |
| 7425 } | 7788 } |
| 7426 } | 7789 } |
| 7427 CPU::FlushICache(instruction_start(), instruction_size()); | 7790 CPU::FlushICache(instruction_start(), instruction_size()); |
| 7428 } | 7791 } |
| 7429 | 7792 |
| 7430 | 7793 |
| 7431 // Locate the source position which is closest to the address in the code. This | 7794 // Locate the source position which is closest to the address in the code. This |
| 7432 // is using the source position information embedded in the relocation info. | 7795 // is using the source position information embedded in the relocation info. |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7840 (elements()->map()->has_fast_smi_only_elements() || | 8203 (elements()->map()->has_fast_smi_only_elements() || |
| 7841 elements() == heap->empty_fixed_array()); | 8204 elements() == heap->empty_fixed_array()); |
| 7842 ElementsKind elements_kind = has_fast_smi_only_elements | 8205 ElementsKind elements_kind = has_fast_smi_only_elements |
| 7843 ? FAST_SMI_ONLY_ELEMENTS | 8206 ? FAST_SMI_ONLY_ELEMENTS |
| 7844 : FAST_ELEMENTS; | 8207 : FAST_ELEMENTS; |
| 7845 MaybeObject* maybe = GetElementsTransitionMap(elements_kind); | 8208 MaybeObject* maybe = GetElementsTransitionMap(elements_kind); |
| 7846 if (!maybe->ToObject(&object)) return maybe; | 8209 if (!maybe->ToObject(&object)) return maybe; |
| 7847 new_map = Map::cast(object); | 8210 new_map = Map::cast(object); |
| 7848 } | 8211 } |
| 7849 | 8212 |
| 8213 FixedArrayBase* old_elements_raw = elements(); |
| 7850 ElementsKind elements_kind = GetElementsKind(); | 8214 ElementsKind elements_kind = GetElementsKind(); |
| 7851 switch (elements_kind) { | 8215 switch (elements_kind) { |
| 7852 case FAST_SMI_ONLY_ELEMENTS: | 8216 case FAST_SMI_ONLY_ELEMENTS: |
| 7853 case FAST_ELEMENTS: { | 8217 case FAST_ELEMENTS: { |
| 7854 AssertNoAllocation no_gc; | 8218 AssertNoAllocation no_gc; |
| 7855 WriteBarrierMode mode(new_elements->GetWriteBarrierMode(no_gc)); | 8219 WriteBarrierMode mode(new_elements->GetWriteBarrierMode(no_gc)); |
| 7856 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); | 8220 CopyFastElementsToFast(FixedArray::cast(old_elements_raw), |
| 8221 new_elements, mode); |
| 7857 set_map(new_map); | 8222 set_map(new_map); |
| 7858 set_elements(new_elements); | 8223 set_elements(new_elements); |
| 7859 break; | 8224 break; |
| 7860 } | 8225 } |
| 7861 case DICTIONARY_ELEMENTS: { | 8226 case DICTIONARY_ELEMENTS: { |
| 7862 AssertNoAllocation no_gc; | 8227 AssertNoAllocation no_gc; |
| 7863 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 8228 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
| 7864 CopySlowElementsToFast(NumberDictionary::cast(elements()), | 8229 CopySlowElementsToFast(NumberDictionary::cast(old_elements_raw), |
| 7865 new_elements, | 8230 new_elements, |
| 7866 mode); | 8231 mode); |
| 7867 set_map(new_map); | 8232 set_map(new_map); |
| 7868 set_elements(new_elements); | 8233 set_elements(new_elements); |
| 7869 break; | 8234 break; |
| 7870 } | 8235 } |
| 7871 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 8236 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 7872 AssertNoAllocation no_gc; | 8237 AssertNoAllocation no_gc; |
| 7873 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | 8238 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
| 7874 // The object's map and the parameter map are unchanged, the unaliased | 8239 // The object's map and the parameter map are unchanged, the unaliased |
| 7875 // arguments are copied to the new backing store. | 8240 // arguments are copied to the new backing store. |
| 7876 FixedArray* parameter_map = FixedArray::cast(elements()); | 8241 FixedArray* parameter_map = FixedArray::cast(old_elements_raw); |
| 7877 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 8242 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 7878 if (arguments->IsDictionary()) { | 8243 if (arguments->IsDictionary()) { |
| 7879 CopySlowElementsToFast(NumberDictionary::cast(arguments), | 8244 CopySlowElementsToFast(NumberDictionary::cast(arguments), |
| 7880 new_elements, | 8245 new_elements, |
| 7881 mode); | 8246 mode); |
| 7882 } else { | 8247 } else { |
| 7883 CopyFastElementsToFast(arguments, new_elements, mode); | 8248 CopyFastElementsToFast(arguments, new_elements, mode); |
| 7884 } | 8249 } |
| 7885 parameter_map->set(1, new_elements); | 8250 parameter_map->set(1, new_elements); |
| 7886 break; | 8251 break; |
| 7887 } | 8252 } |
| 7888 case FAST_DOUBLE_ELEMENTS: { | 8253 case FAST_DOUBLE_ELEMENTS: { |
| 7889 FixedDoubleArray* old_elements = FixedDoubleArray::cast(elements()); | 8254 FixedDoubleArray* old_elements = FixedDoubleArray::cast(old_elements_raw); |
| 7890 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); | 8255 uint32_t old_length = static_cast<uint32_t>(old_elements->length()); |
| 7891 // Fill out the new array with this content and array holes. | 8256 // Fill out the new array with this content and array holes. |
| 7892 for (uint32_t i = 0; i < old_length; i++) { | 8257 for (uint32_t i = 0; i < old_length; i++) { |
| 7893 if (!old_elements->is_the_hole(i)) { | 8258 if (!old_elements->is_the_hole(i)) { |
| 7894 Object* obj; | 8259 Object* obj; |
| 7895 // Objects must be allocated in the old object space, since the | 8260 // Objects must be allocated in the old object space, since the |
| 7896 // overall number of HeapNumbers needed for the conversion might | 8261 // overall number of HeapNumbers needed for the conversion might |
| 7897 // exceed the capacity of new space, and we would fail repeatedly | 8262 // exceed the capacity of new space, and we would fail repeatedly |
| 7898 // trying to convert the FixedDoubleArray. | 8263 // trying to convert the FixedDoubleArray. |
| 7899 MaybeObject* maybe_value_object = | 8264 MaybeObject* maybe_value_object = |
| (...skipping 17 matching lines...) Expand all Loading... |
| 7917 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8282 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7918 case EXTERNAL_INT_ELEMENTS: | 8283 case EXTERNAL_INT_ELEMENTS: |
| 7919 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8284 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7920 case EXTERNAL_FLOAT_ELEMENTS: | 8285 case EXTERNAL_FLOAT_ELEMENTS: |
| 7921 case EXTERNAL_DOUBLE_ELEMENTS: | 8286 case EXTERNAL_DOUBLE_ELEMENTS: |
| 7922 case EXTERNAL_PIXEL_ELEMENTS: | 8287 case EXTERNAL_PIXEL_ELEMENTS: |
| 7923 UNREACHABLE(); | 8288 UNREACHABLE(); |
| 7924 break; | 8289 break; |
| 7925 } | 8290 } |
| 7926 | 8291 |
| 8292 if (FLAG_trace_elements_transitions) { |
| 8293 PrintElementsTransition(stdout, elements_kind, old_elements_raw, |
| 8294 FAST_ELEMENTS, new_elements); |
| 8295 } |
| 8296 |
| 7927 // Update the length if necessary. | 8297 // Update the length if necessary. |
| 7928 if (IsJSArray()) { | 8298 if (IsJSArray()) { |
| 7929 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8299 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
| 7930 } | 8300 } |
| 7931 | 8301 |
| 7932 return new_elements; | 8302 return new_elements; |
| 7933 } | 8303 } |
| 7934 | 8304 |
| 7935 | 8305 |
| 7936 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( | 8306 MaybeObject* JSObject::SetFastDoubleElementsCapacityAndLength( |
| 7937 int capacity, | 8307 int capacity, |
| 7938 int length) { | 8308 int length) { |
| 7939 Heap* heap = GetHeap(); | 8309 Heap* heap = GetHeap(); |
| 7940 // We should never end in here with a pixel or external array. | 8310 // We should never end in here with a pixel or external array. |
| 7941 ASSERT(!HasExternalArrayElements()); | 8311 ASSERT(!HasExternalArrayElements()); |
| 7942 | 8312 |
| 7943 Object* obj; | 8313 Object* obj; |
| 7944 { MaybeObject* maybe_obj = | 8314 { MaybeObject* maybe_obj = |
| 7945 heap->AllocateUninitializedFixedDoubleArray(capacity); | 8315 heap->AllocateUninitializedFixedDoubleArray(capacity); |
| 7946 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8316 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7947 } | 8317 } |
| 7948 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); | 8318 FixedDoubleArray* elems = FixedDoubleArray::cast(obj); |
| 7949 | 8319 |
| 7950 { MaybeObject* maybe_obj = | 8320 { MaybeObject* maybe_obj = |
| 7951 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); | 8321 GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); |
| 7952 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8322 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7953 } | 8323 } |
| 7954 Map* new_map = Map::cast(obj); | 8324 Map* new_map = Map::cast(obj); |
| 7955 | 8325 |
| 8326 FixedArrayBase* old_elements = elements(); |
| 8327 ElementsKind elements_kind(GetElementsKind()); |
| 7956 AssertNoAllocation no_gc; | 8328 AssertNoAllocation no_gc; |
| 7957 switch (GetElementsKind()) { | 8329 switch (elements_kind) { |
| 7958 case FAST_SMI_ONLY_ELEMENTS: | 8330 case FAST_SMI_ONLY_ELEMENTS: |
| 7959 case FAST_ELEMENTS: { | 8331 case FAST_ELEMENTS: { |
| 7960 elems->Initialize(FixedArray::cast(elements())); | 8332 elems->Initialize(FixedArray::cast(old_elements)); |
| 7961 break; | 8333 break; |
| 7962 } | 8334 } |
| 7963 case FAST_DOUBLE_ELEMENTS: { | 8335 case FAST_DOUBLE_ELEMENTS: { |
| 7964 elems->Initialize(FixedDoubleArray::cast(elements())); | 8336 elems->Initialize(FixedDoubleArray::cast(old_elements)); |
| 7965 break; | 8337 break; |
| 7966 } | 8338 } |
| 7967 case DICTIONARY_ELEMENTS: { | 8339 case DICTIONARY_ELEMENTS: { |
| 7968 elems->Initialize(NumberDictionary::cast(elements())); | 8340 elems->Initialize(NumberDictionary::cast(old_elements)); |
| 7969 break; | 8341 break; |
| 7970 } | 8342 } |
| 7971 default: | 8343 default: |
| 7972 UNREACHABLE(); | 8344 UNREACHABLE(); |
| 7973 break; | 8345 break; |
| 7974 } | 8346 } |
| 7975 | 8347 |
| 8348 if (FLAG_trace_elements_transitions) { |
| 8349 PrintElementsTransition(stdout, elements_kind, old_elements, |
| 8350 FAST_DOUBLE_ELEMENTS, elems); |
| 8351 } |
| 8352 |
| 7976 ASSERT(new_map->has_fast_double_elements()); | 8353 ASSERT(new_map->has_fast_double_elements()); |
| 7977 set_map(new_map); | 8354 set_map(new_map); |
| 7978 ASSERT(elems->IsFixedDoubleArray()); | 8355 ASSERT(elems->IsFixedDoubleArray()); |
| 7979 set_elements(elems); | 8356 set_elements(elems); |
| 7980 | 8357 |
| 7981 if (IsJSArray()) { | 8358 if (IsJSArray()) { |
| 7982 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 8359 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
| 7983 } | 8360 } |
| 7984 | 8361 |
| 7985 return this; | 8362 return this; |
| 7986 } | 8363 } |
| 7987 | 8364 |
| 7988 | 8365 |
| 7989 MaybeObject* JSObject::SetSlowElements(Object* len) { | 8366 MaybeObject* JSObject::SetSlowElements(Object* len) { |
| 7990 // We should never end in here with a pixel or external array. | 8367 // We should never end in here with a pixel or external array. |
| 7991 ASSERT(!HasExternalArrayElements()); | 8368 ASSERT(!HasExternalArrayElements()); |
| 7992 | 8369 |
| 7993 uint32_t new_length = static_cast<uint32_t>(len->Number()); | 8370 uint32_t new_length = static_cast<uint32_t>(len->Number()); |
| 7994 | 8371 |
| 7995 switch (GetElementsKind()) { | 8372 FixedArrayBase* old_elements = elements(); |
| 8373 ElementsKind elements_kind = GetElementsKind(); |
| 8374 switch (elements_kind) { |
| 7996 case FAST_SMI_ONLY_ELEMENTS: | 8375 case FAST_SMI_ONLY_ELEMENTS: |
| 7997 case FAST_ELEMENTS: | 8376 case FAST_ELEMENTS: |
| 7998 case FAST_DOUBLE_ELEMENTS: { | 8377 case FAST_DOUBLE_ELEMENTS: { |
| 7999 // Make sure we never try to shrink dense arrays into sparse arrays. | 8378 // Make sure we never try to shrink dense arrays into sparse arrays. |
| 8000 ASSERT(static_cast<uint32_t>( | 8379 ASSERT(static_cast<uint32_t>(old_elements->length()) <= new_length); |
| 8001 FixedArrayBase::cast(elements())->length()) <= new_length); | |
| 8002 MaybeObject* result = NormalizeElements(); | 8380 MaybeObject* result = NormalizeElements(); |
| 8003 if (result->IsFailure()) return result; | 8381 if (result->IsFailure()) return result; |
| 8004 | 8382 |
| 8005 // Update length for JSArrays. | 8383 // Update length for JSArrays. |
| 8006 if (IsJSArray()) JSArray::cast(this)->set_length(len); | 8384 if (IsJSArray()) JSArray::cast(this)->set_length(len); |
| 8007 break; | 8385 break; |
| 8008 } | 8386 } |
| 8009 case DICTIONARY_ELEMENTS: { | 8387 case DICTIONARY_ELEMENTS: { |
| 8010 if (IsJSArray()) { | 8388 if (IsJSArray()) { |
| 8011 uint32_t old_length = | 8389 uint32_t old_length = |
| (...skipping 11 matching lines...) Expand all Loading... |
| 8023 case EXTERNAL_SHORT_ELEMENTS: | 8401 case EXTERNAL_SHORT_ELEMENTS: |
| 8024 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8402 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 8025 case EXTERNAL_INT_ELEMENTS: | 8403 case EXTERNAL_INT_ELEMENTS: |
| 8026 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8404 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 8027 case EXTERNAL_FLOAT_ELEMENTS: | 8405 case EXTERNAL_FLOAT_ELEMENTS: |
| 8028 case EXTERNAL_DOUBLE_ELEMENTS: | 8406 case EXTERNAL_DOUBLE_ELEMENTS: |
| 8029 case EXTERNAL_PIXEL_ELEMENTS: | 8407 case EXTERNAL_PIXEL_ELEMENTS: |
| 8030 UNREACHABLE(); | 8408 UNREACHABLE(); |
| 8031 break; | 8409 break; |
| 8032 } | 8410 } |
| 8411 |
| 8412 if (FLAG_trace_elements_transitions) { |
| 8413 PrintElementsTransition(stdout, elements_kind, old_elements, |
| 8414 DICTIONARY_ELEMENTS, elements()); |
| 8415 } |
| 8416 |
| 8033 return this; | 8417 return this; |
| 8034 } | 8418 } |
| 8035 | 8419 |
| 8036 | 8420 |
| 8037 MaybeObject* JSArray::Initialize(int capacity) { | 8421 MaybeObject* JSArray::Initialize(int capacity) { |
| 8038 Heap* heap = GetHeap(); | 8422 Heap* heap = GetHeap(); |
| 8039 ASSERT(capacity >= 0); | 8423 ASSERT(capacity >= 0); |
| 8040 set_length(Smi::FromInt(0)); | 8424 set_length(Smi::FromInt(0)); |
| 8041 FixedArray* new_elements; | 8425 FixedArray* new_elements; |
| 8042 if (capacity == 0) { | 8426 if (capacity == 0) { |
| (...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8950 if (maybe->IsFailure()) return maybe; | 9334 if (maybe->IsFailure()) return maybe; |
| 8951 FixedDoubleArray::cast(elements())->set(index, value->Number()); | 9335 FixedDoubleArray::cast(elements())->set(index, value->Number()); |
| 8952 return value; | 9336 return value; |
| 8953 } | 9337 } |
| 8954 // Change elements kind from SMI_ONLY to generic FAST if necessary. | 9338 // Change elements kind from SMI_ONLY to generic FAST if necessary. |
| 8955 if (HasFastSmiOnlyElements() && !value->IsSmi()) { | 9339 if (HasFastSmiOnlyElements() && !value->IsSmi()) { |
| 8956 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); | 9340 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); |
| 8957 Map* new_map; | 9341 Map* new_map; |
| 8958 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; | 9342 if (!maybe_new_map->To<Map>(&new_map)) return maybe_new_map; |
| 8959 set_map(new_map); | 9343 set_map(new_map); |
| 9344 if (FLAG_trace_elements_transitions) { |
| 9345 PrintElementsTransition(stdout, FAST_SMI_ONLY_ELEMENTS, elements(), |
| 9346 FAST_ELEMENTS, elements()); |
| 9347 } |
| 8960 } | 9348 } |
| 8961 // Increase backing store capacity if that's been decided previously. | 9349 // Increase backing store capacity if that's been decided previously. |
| 8962 if (new_capacity != capacity) { | 9350 if (new_capacity != capacity) { |
| 8963 Object* new_elements; | 9351 Object* new_elements; |
| 8964 SetFastElementsCapacityMode set_capacity_mode = | 9352 SetFastElementsCapacityMode set_capacity_mode = |
| 8965 value->IsSmi() && HasFastSmiOnlyElements() | 9353 value->IsSmi() && HasFastSmiOnlyElements() |
| 8966 ? kAllowSmiOnlyElements | 9354 ? kAllowSmiOnlyElements |
| 8967 : kDontAllowSmiOnlyElements; | 9355 : kDontAllowSmiOnlyElements; |
| 8968 MaybeObject* maybe = | 9356 MaybeObject* maybe = |
| 8969 SetFastElementsCapacityAndLength(new_capacity, | 9357 SetFastElementsCapacityAndLength(new_capacity, |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9306 } | 9694 } |
| 9307 } | 9695 } |
| 9308 } | 9696 } |
| 9309 // All possible cases have been handled above. Add a return to avoid the | 9697 // All possible cases have been handled above. Add a return to avoid the |
| 9310 // complaints from the compiler. | 9698 // complaints from the compiler. |
| 9311 UNREACHABLE(); | 9699 UNREACHABLE(); |
| 9312 return isolate->heap()->null_value(); | 9700 return isolate->heap()->null_value(); |
| 9313 } | 9701 } |
| 9314 | 9702 |
| 9315 | 9703 |
| 9704 MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( |
| 9705 ElementsKind to_kind) { |
| 9706 ElementsKind from_kind = map()->elements_kind(); |
| 9707 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
| 9708 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
| 9709 uint32_t length = capacity; |
| 9710 if (IsJSArray()) { |
| 9711 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); |
| 9712 } |
| 9713 if (from_kind == FAST_SMI_ONLY_ELEMENTS) { |
| 9714 if (to_kind == FAST_DOUBLE_ELEMENTS) { |
| 9715 MaybeObject* maybe_result = |
| 9716 SetFastDoubleElementsCapacityAndLength(capacity, length); |
| 9717 if (maybe_result->IsFailure()) return maybe_result; |
| 9718 return this; |
| 9719 } else if (to_kind == FAST_ELEMENTS) { |
| 9720 MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); |
| 9721 Map* new_map; |
| 9722 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 9723 set_map(new_map); |
| 9724 return this; |
| 9725 } |
| 9726 } else if (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS) { |
| 9727 MaybeObject* maybe_result = SetFastElementsCapacityAndLength( |
| 9728 capacity, length, kDontAllowSmiOnlyElements); |
| 9729 if (maybe_result->IsFailure()) return maybe_result; |
| 9730 return this; |
| 9731 } |
| 9732 // This method should never be called for any other case than the ones |
| 9733 // handled above. |
| 9734 UNREACHABLE(); |
| 9735 return GetIsolate()->heap()->null_value(); |
| 9736 } |
| 9737 |
| 9738 |
| 9739 // static |
| 9740 bool Map::IsValidElementsTransition(ElementsKind from_kind, |
| 9741 ElementsKind to_kind) { |
| 9742 return |
| 9743 (from_kind == FAST_SMI_ONLY_ELEMENTS && |
| 9744 (to_kind == FAST_DOUBLE_ELEMENTS || to_kind == FAST_ELEMENTS)) || |
| 9745 (from_kind == FAST_DOUBLE_ELEMENTS && to_kind == FAST_ELEMENTS); |
| 9746 } |
| 9747 |
| 9748 |
| 9316 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, | 9749 MaybeObject* JSArray::JSArrayUpdateLengthFromIndex(uint32_t index, |
| 9317 Object* value) { | 9750 Object* value) { |
| 9318 uint32_t old_len = 0; | 9751 uint32_t old_len = 0; |
| 9319 CHECK(length()->ToArrayIndex(&old_len)); | 9752 CHECK(length()->ToArrayIndex(&old_len)); |
| 9320 // Check to see if we need to update the length. For now, we make | 9753 // Check to see if we need to update the length. For now, we make |
| 9321 // sure that the length stays within 32-bits (unsigned). | 9754 // sure that the length stays within 32-bits (unsigned). |
| 9322 if (index >= old_len && index != 0xffffffff) { | 9755 if (index >= old_len && index != 0xffffffff) { |
| 9323 Object* len; | 9756 Object* len; |
| 9324 { MaybeObject* maybe_len = | 9757 { MaybeObject* maybe_len = |
| 9325 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); | 9758 GetHeap()->NumberFromDouble(static_cast<double>(index) + 1); |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9572 constructor->shared()->get_api_func_data()->indexed_property_handler(); | 10005 constructor->shared()->get_api_func_data()->indexed_property_handler(); |
| 9573 return InterceptorInfo::cast(result); | 10006 return InterceptorInfo::cast(result); |
| 9574 } | 10007 } |
| 9575 | 10008 |
| 9576 | 10009 |
| 9577 MaybeObject* JSObject::GetPropertyPostInterceptor( | 10010 MaybeObject* JSObject::GetPropertyPostInterceptor( |
| 9578 JSReceiver* receiver, | 10011 JSReceiver* receiver, |
| 9579 String* name, | 10012 String* name, |
| 9580 PropertyAttributes* attributes) { | 10013 PropertyAttributes* attributes) { |
| 9581 // Check local property in holder, ignore interceptor. | 10014 // Check local property in holder, ignore interceptor. |
| 9582 LookupResult result; | 10015 LookupResult result(GetIsolate()); |
| 9583 LocalLookupRealNamedProperty(name, &result); | 10016 LocalLookupRealNamedProperty(name, &result); |
| 9584 if (result.IsProperty()) { | 10017 if (result.IsProperty()) { |
| 9585 return GetProperty(receiver, &result, name, attributes); | 10018 return GetProperty(receiver, &result, name, attributes); |
| 9586 } | 10019 } |
| 9587 // Continue searching via the prototype chain. | 10020 // Continue searching via the prototype chain. |
| 9588 Object* pt = GetPrototype(); | 10021 Object* pt = GetPrototype(); |
| 9589 *attributes = ABSENT; | 10022 *attributes = ABSENT; |
| 9590 if (pt->IsNull()) return GetHeap()->undefined_value(); | 10023 if (pt->IsNull()) return GetHeap()->undefined_value(); |
| 9591 return pt->GetPropertyWithReceiver(receiver, name, attributes); | 10024 return pt->GetPropertyWithReceiver(receiver, name, attributes); |
| 9592 } | 10025 } |
| 9593 | 10026 |
| 9594 | 10027 |
| 9595 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( | 10028 MaybeObject* JSObject::GetLocalPropertyPostInterceptor( |
| 9596 JSReceiver* receiver, | 10029 JSReceiver* receiver, |
| 9597 String* name, | 10030 String* name, |
| 9598 PropertyAttributes* attributes) { | 10031 PropertyAttributes* attributes) { |
| 9599 // Check local property in holder, ignore interceptor. | 10032 // Check local property in holder, ignore interceptor. |
| 9600 LookupResult result; | 10033 LookupResult result(GetIsolate()); |
| 9601 LocalLookupRealNamedProperty(name, &result); | 10034 LocalLookupRealNamedProperty(name, &result); |
| 9602 if (result.IsProperty()) { | 10035 if (result.IsProperty()) { |
| 9603 return GetProperty(receiver, &result, name, attributes); | 10036 return GetProperty(receiver, &result, name, attributes); |
| 9604 } | 10037 } |
| 9605 return GetHeap()->undefined_value(); | 10038 return GetHeap()->undefined_value(); |
| 9606 } | 10039 } |
| 9607 | 10040 |
| 9608 | 10041 |
| 9609 MaybeObject* JSObject::GetPropertyWithInterceptor( | 10042 MaybeObject* JSObject::GetPropertyWithInterceptor( |
| 9610 JSReceiver* receiver, | 10043 JSReceiver* receiver, |
| (...skipping 30 matching lines...) Expand all Loading... |
| 9641 *receiver_handle, | 10074 *receiver_handle, |
| 9642 *name_handle, | 10075 *name_handle, |
| 9643 attributes); | 10076 attributes); |
| 9644 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 10077 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 9645 return result; | 10078 return result; |
| 9646 } | 10079 } |
| 9647 | 10080 |
| 9648 | 10081 |
| 9649 bool JSObject::HasRealNamedProperty(String* key) { | 10082 bool JSObject::HasRealNamedProperty(String* key) { |
| 9650 // Check access rights if needed. | 10083 // Check access rights if needed. |
| 10084 Isolate* isolate = GetIsolate(); |
| 9651 if (IsAccessCheckNeeded()) { | 10085 if (IsAccessCheckNeeded()) { |
| 9652 Heap* heap = GetHeap(); | 10086 if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 9653 if (!heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 10087 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 9654 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | |
| 9655 return false; | 10088 return false; |
| 9656 } | 10089 } |
| 9657 } | 10090 } |
| 9658 | 10091 |
| 9659 LookupResult result; | 10092 LookupResult result(isolate); |
| 9660 LocalLookupRealNamedProperty(key, &result); | 10093 LocalLookupRealNamedProperty(key, &result); |
| 9661 return result.IsProperty() && (result.type() != INTERCEPTOR); | 10094 return result.IsProperty() && (result.type() != INTERCEPTOR); |
| 9662 } | 10095 } |
| 9663 | 10096 |
| 9664 | 10097 |
| 9665 bool JSObject::HasRealElementProperty(uint32_t index) { | 10098 bool JSObject::HasRealElementProperty(uint32_t index) { |
| 9666 // Check access rights if needed. | 10099 // Check access rights if needed. |
| 9667 if (IsAccessCheckNeeded()) { | 10100 if (IsAccessCheckNeeded()) { |
| 9668 Heap* heap = GetHeap(); | 10101 Heap* heap = GetHeap(); |
| 9669 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 10102 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9718 break; | 10151 break; |
| 9719 } | 10152 } |
| 9720 // All possibilities have been handled above already. | 10153 // All possibilities have been handled above already. |
| 9721 UNREACHABLE(); | 10154 UNREACHABLE(); |
| 9722 return GetHeap()->null_value(); | 10155 return GetHeap()->null_value(); |
| 9723 } | 10156 } |
| 9724 | 10157 |
| 9725 | 10158 |
| 9726 bool JSObject::HasRealNamedCallbackProperty(String* key) { | 10159 bool JSObject::HasRealNamedCallbackProperty(String* key) { |
| 9727 // Check access rights if needed. | 10160 // Check access rights if needed. |
| 10161 Isolate* isolate = GetIsolate(); |
| 9728 if (IsAccessCheckNeeded()) { | 10162 if (IsAccessCheckNeeded()) { |
| 9729 Heap* heap = GetHeap(); | 10163 if (!isolate->MayNamedAccess(this, key, v8::ACCESS_HAS)) { |
| 9730 if (!heap->isolate()->MayNamedAccess(this, key, v8::ACCESS_HAS)) { | 10164 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); |
| 9731 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | |
| 9732 return false; | 10165 return false; |
| 9733 } | 10166 } |
| 9734 } | 10167 } |
| 9735 | 10168 |
| 9736 LookupResult result; | 10169 LookupResult result(isolate); |
| 9737 LocalLookupRealNamedProperty(key, &result); | 10170 LocalLookupRealNamedProperty(key, &result); |
| 9738 return result.IsProperty() && (result.type() == CALLBACKS); | 10171 return result.IsProperty() && (result.type() == CALLBACKS); |
| 9739 } | 10172 } |
| 9740 | 10173 |
| 9741 | 10174 |
| 9742 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { | 10175 int JSObject::NumberOfLocalProperties(PropertyAttributes filter) { |
| 9743 if (HasFastProperties()) { | 10176 if (HasFastProperties()) { |
| 9744 DescriptorArray* descs = map()->instance_descriptors(); | 10177 DescriptorArray* descs = map()->instance_descriptors(); |
| 9745 int result = 0; | 10178 int result = 0; |
| 9746 for (int i = 0; i < descs->number_of_descriptors(); i++) { | 10179 for (int i = 0; i < descs->number_of_descriptors(); i++) { |
| (...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10591 | 11024 |
| 10592 // Force instantiation of template instances class. | 11025 // Force instantiation of template instances class. |
| 10593 // Please note this list is compiler dependent. | 11026 // Please note this list is compiler dependent. |
| 10594 | 11027 |
| 10595 template class HashTable<SymbolTableShape, HashTableKey*>; | 11028 template class HashTable<SymbolTableShape, HashTableKey*>; |
| 10596 | 11029 |
| 10597 template class HashTable<CompilationCacheShape, HashTableKey*>; | 11030 template class HashTable<CompilationCacheShape, HashTableKey*>; |
| 10598 | 11031 |
| 10599 template class HashTable<MapCacheShape, HashTableKey*>; | 11032 template class HashTable<MapCacheShape, HashTableKey*>; |
| 10600 | 11033 |
| 10601 template class HashTable<ObjectHashTableShape, JSReceiver*>; | 11034 template class HashTable<ObjectHashTableShape<1>, Object*>; |
| 11035 |
| 11036 template class HashTable<ObjectHashTableShape<2>, Object*>; |
| 10602 | 11037 |
| 10603 template class Dictionary<StringDictionaryShape, String*>; | 11038 template class Dictionary<StringDictionaryShape, String*>; |
| 10604 | 11039 |
| 10605 template class Dictionary<NumberDictionaryShape, uint32_t>; | 11040 template class Dictionary<NumberDictionaryShape, uint32_t>; |
| 10606 | 11041 |
| 10607 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( | 11042 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( |
| 10608 int); | 11043 int); |
| 10609 | 11044 |
| 10610 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( | 11045 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( |
| 10611 int); | 11046 int); |
| (...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11082 } | 11517 } |
| 11083 | 11518 |
| 11084 | 11519 |
| 11085 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { | 11520 JSGlobalPropertyCell* GlobalObject::GetPropertyCell(LookupResult* result) { |
| 11086 ASSERT(!HasFastProperties()); | 11521 ASSERT(!HasFastProperties()); |
| 11087 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 11522 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 11088 return JSGlobalPropertyCell::cast(value); | 11523 return JSGlobalPropertyCell::cast(value); |
| 11089 } | 11524 } |
| 11090 | 11525 |
| 11091 | 11526 |
| 11527 Handle<JSGlobalPropertyCell> GlobalObject::EnsurePropertyCell( |
| 11528 Handle<GlobalObject> global, |
| 11529 Handle<String> name) { |
| 11530 Isolate* isolate = global->GetIsolate(); |
| 11531 CALL_HEAP_FUNCTION(isolate, |
| 11532 global->EnsurePropertyCell(*name), |
| 11533 JSGlobalPropertyCell); |
| 11534 } |
| 11535 |
| 11536 |
| 11092 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { | 11537 MaybeObject* GlobalObject::EnsurePropertyCell(String* name) { |
| 11093 ASSERT(!HasFastProperties()); | 11538 ASSERT(!HasFastProperties()); |
| 11094 int entry = property_dictionary()->FindEntry(name); | 11539 int entry = property_dictionary()->FindEntry(name); |
| 11095 if (entry == StringDictionary::kNotFound) { | 11540 if (entry == StringDictionary::kNotFound) { |
| 11096 Heap* heap = GetHeap(); | 11541 Heap* heap = GetHeap(); |
| 11097 Object* cell; | 11542 Object* cell; |
| 11098 { MaybeObject* maybe_cell = | 11543 { MaybeObject* maybe_cell = |
| 11099 heap->AllocateJSGlobalPropertyCell(heap->the_hole_value()); | 11544 heap->AllocateJSGlobalPropertyCell(heap->the_hole_value()); |
| 11100 if (!maybe_cell->ToObject(&cell)) return maybe_cell; | 11545 if (!maybe_cell->ToObject(&cell)) return maybe_cell; |
| 11101 } | 11546 } |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11319 cache->ElementAdded(); | 11764 cache->ElementAdded(); |
| 11320 return cache; | 11765 return cache; |
| 11321 } | 11766 } |
| 11322 | 11767 |
| 11323 | 11768 |
| 11324 MaybeObject* CompilationCacheTable::PutEval(String* src, | 11769 MaybeObject* CompilationCacheTable::PutEval(String* src, |
| 11325 Context* context, | 11770 Context* context, |
| 11326 SharedFunctionInfo* value) { | 11771 SharedFunctionInfo* value) { |
| 11327 StringSharedKey key(src, | 11772 StringSharedKey key(src, |
| 11328 context->closure()->shared(), | 11773 context->closure()->shared(), |
| 11329 value->strict_mode() ? kStrictMode : kNonStrictMode); | 11774 value->strict_mode_flag()); |
| 11330 Object* obj; | 11775 Object* obj; |
| 11331 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 11776 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 11332 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 11777 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11333 } | 11778 } |
| 11334 | 11779 |
| 11335 CompilationCacheTable* cache = | 11780 CompilationCacheTable* cache = |
| 11336 reinterpret_cast<CompilationCacheTable*>(obj); | 11781 reinterpret_cast<CompilationCacheTable*>(obj); |
| 11337 int entry = cache->FindInsertionEntry(key.Hash()); | 11782 int entry = cache->FindInsertionEntry(key.Hash()); |
| 11338 | 11783 |
| 11339 Object* k; | 11784 Object* k; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 11368 return cache; | 11813 return cache; |
| 11369 } | 11814 } |
| 11370 | 11815 |
| 11371 | 11816 |
| 11372 void CompilationCacheTable::Remove(Object* value) { | 11817 void CompilationCacheTable::Remove(Object* value) { |
| 11373 Object* null_value = GetHeap()->null_value(); | 11818 Object* null_value = GetHeap()->null_value(); |
| 11374 for (int entry = 0, size = Capacity(); entry < size; entry++) { | 11819 for (int entry = 0, size = Capacity(); entry < size; entry++) { |
| 11375 int entry_index = EntryToIndex(entry); | 11820 int entry_index = EntryToIndex(entry); |
| 11376 int value_index = entry_index + 1; | 11821 int value_index = entry_index + 1; |
| 11377 if (get(value_index) == value) { | 11822 if (get(value_index) == value) { |
| 11378 fast_set(this, entry_index, null_value); | 11823 NoWriteBarrierSet(this, entry_index, null_value); |
| 11379 fast_set(this, value_index, null_value); | 11824 NoWriteBarrierSet(this, value_index, null_value); |
| 11380 ElementRemoved(); | 11825 ElementRemoved(); |
| 11381 } | 11826 } |
| 11382 } | 11827 } |
| 11383 return; | 11828 return; |
| 11384 } | 11829 } |
| 11385 | 11830 |
| 11386 | 11831 |
| 11387 // SymbolsKey used for HashTable where key is array of symbols. | 11832 // SymbolsKey used for HashTable where key is array of symbols. |
| 11388 class SymbolsKey : public HashTableKey { | 11833 class SymbolsKey : public HashTableKey { |
| 11389 public: | 11834 public: |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11841 ASSERT(type != FIELD); | 12286 ASSERT(type != FIELD); |
| 11842 instance_descriptor_length++; | 12287 instance_descriptor_length++; |
| 11843 if (type == NORMAL && | 12288 if (type == NORMAL && |
| 11844 (!value->IsJSFunction() || heap->InNewSpace(value))) { | 12289 (!value->IsJSFunction() || heap->InNewSpace(value))) { |
| 11845 number_of_fields += 1; | 12290 number_of_fields += 1; |
| 11846 } | 12291 } |
| 11847 } | 12292 } |
| 11848 } | 12293 } |
| 11849 | 12294 |
| 11850 // Allocate the instance descriptor. | 12295 // Allocate the instance descriptor. |
| 11851 Object* descriptors_unchecked; | 12296 DescriptorArray* descriptors; |
| 11852 { MaybeObject* maybe_descriptors_unchecked = | 12297 { MaybeObject* maybe_descriptors = |
| 11853 DescriptorArray::Allocate(instance_descriptor_length); | 12298 DescriptorArray::Allocate(instance_descriptor_length); |
| 11854 if (!maybe_descriptors_unchecked->ToObject(&descriptors_unchecked)) { | 12299 if (!maybe_descriptors->To<DescriptorArray>(&descriptors)) { |
| 11855 return maybe_descriptors_unchecked; | 12300 return maybe_descriptors; |
| 11856 } | 12301 } |
| 11857 } | 12302 } |
| 11858 DescriptorArray* descriptors = DescriptorArray::cast(descriptors_unchecked); | 12303 |
| 12304 DescriptorArray::WhitenessWitness witness(descriptors); |
| 11859 | 12305 |
| 11860 int inobject_props = obj->map()->inobject_properties(); | 12306 int inobject_props = obj->map()->inobject_properties(); |
| 11861 int number_of_allocated_fields = | 12307 int number_of_allocated_fields = |
| 11862 number_of_fields + unused_property_fields - inobject_props; | 12308 number_of_fields + unused_property_fields - inobject_props; |
| 11863 if (number_of_allocated_fields < 0) { | 12309 if (number_of_allocated_fields < 0) { |
| 11864 // There is enough inobject space for all fields (including unused). | 12310 // There is enough inobject space for all fields (including unused). |
| 11865 number_of_allocated_fields = 0; | 12311 number_of_allocated_fields = 0; |
| 11866 unused_property_fields = inobject_props - number_of_fields; | 12312 unused_property_fields = inobject_props - number_of_fields; |
| 11867 } | 12313 } |
| 11868 | 12314 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 11886 if (!maybe_key->ToObject(&key)) return maybe_key; | 12332 if (!maybe_key->ToObject(&key)) return maybe_key; |
| 11887 } | 12333 } |
| 11888 PropertyDetails details = DetailsAt(i); | 12334 PropertyDetails details = DetailsAt(i); |
| 11889 PropertyType type = details.type(); | 12335 PropertyType type = details.type(); |
| 11890 | 12336 |
| 11891 if (value->IsJSFunction() && !heap->InNewSpace(value)) { | 12337 if (value->IsJSFunction() && !heap->InNewSpace(value)) { |
| 11892 ConstantFunctionDescriptor d(String::cast(key), | 12338 ConstantFunctionDescriptor d(String::cast(key), |
| 11893 JSFunction::cast(value), | 12339 JSFunction::cast(value), |
| 11894 details.attributes(), | 12340 details.attributes(), |
| 11895 details.index()); | 12341 details.index()); |
| 11896 descriptors->Set(next_descriptor++, &d); | 12342 descriptors->Set(next_descriptor++, &d, witness); |
| 11897 } else if (type == NORMAL) { | 12343 } else if (type == NORMAL) { |
| 11898 if (current_offset < inobject_props) { | 12344 if (current_offset < inobject_props) { |
| 11899 obj->InObjectPropertyAtPut(current_offset, | 12345 obj->InObjectPropertyAtPut(current_offset, |
| 11900 value, | 12346 value, |
| 11901 UPDATE_WRITE_BARRIER); | 12347 UPDATE_WRITE_BARRIER); |
| 11902 } else { | 12348 } else { |
| 11903 int offset = current_offset - inobject_props; | 12349 int offset = current_offset - inobject_props; |
| 11904 FixedArray::cast(fields)->set(offset, value); | 12350 FixedArray::cast(fields)->set(offset, value); |
| 11905 } | 12351 } |
| 11906 FieldDescriptor d(String::cast(key), | 12352 FieldDescriptor d(String::cast(key), |
| 11907 current_offset++, | 12353 current_offset++, |
| 11908 details.attributes(), | 12354 details.attributes(), |
| 11909 details.index()); | 12355 details.index()); |
| 11910 descriptors->Set(next_descriptor++, &d); | 12356 descriptors->Set(next_descriptor++, &d, witness); |
| 11911 } else if (type == CALLBACKS) { | 12357 } else if (type == CALLBACKS) { |
| 11912 CallbacksDescriptor d(String::cast(key), | 12358 CallbacksDescriptor d(String::cast(key), |
| 11913 value, | 12359 value, |
| 11914 details.attributes(), | 12360 details.attributes(), |
| 11915 details.index()); | 12361 details.index()); |
| 11916 descriptors->Set(next_descriptor++, &d); | 12362 descriptors->Set(next_descriptor++, &d, witness); |
| 11917 } else { | 12363 } else { |
| 11918 UNREACHABLE(); | 12364 UNREACHABLE(); |
| 11919 } | 12365 } |
| 11920 } | 12366 } |
| 11921 } | 12367 } |
| 11922 ASSERT(current_offset == number_of_fields); | 12368 ASSERT(current_offset == number_of_fields); |
| 11923 | 12369 |
| 11924 descriptors->Sort(); | 12370 descriptors->Sort(witness); |
| 11925 // Allocate new map. | 12371 // Allocate new map. |
| 11926 Object* new_map; | 12372 Object* new_map; |
| 11927 { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); | 12373 { MaybeObject* maybe_new_map = obj->map()->CopyDropDescriptors(); |
| 11928 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; | 12374 if (!maybe_new_map->ToObject(&new_map)) return maybe_new_map; |
| 11929 } | 12375 } |
| 11930 | 12376 |
| 11931 // Transform the object. | 12377 // Transform the object. |
| 11932 obj->set_map(Map::cast(new_map)); | 12378 obj->set_map(Map::cast(new_map)); |
| 11933 obj->map()->set_instance_descriptors(descriptors); | 12379 obj->map()->set_instance_descriptors(descriptors); |
| 11934 obj->map()->set_unused_property_fields(unused_property_fields); | 12380 obj->map()->set_unused_property_fields(unused_property_fields); |
| 11935 | 12381 |
| 11936 obj->set_properties(FixedArray::cast(fields)); | 12382 obj->set_properties(FixedArray::cast(fields)); |
| 11937 ASSERT(obj->IsJSObject()); | 12383 ASSERT(obj->IsJSObject()); |
| 11938 | 12384 |
| 11939 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); | 12385 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); |
| 11940 // Check that it really works. | 12386 // Check that it really works. |
| 11941 ASSERT(obj->HasFastProperties()); | 12387 ASSERT(obj->HasFastProperties()); |
| 11942 | 12388 |
| 11943 return obj; | 12389 return obj; |
| 11944 } | 12390 } |
| 11945 | 12391 |
| 11946 | 12392 |
| 11947 Object* ObjectHashTable::Lookup(JSReceiver* key) { | 12393 bool ObjectHashSet::Contains(Object* key) { |
| 11948 // If the object does not have an identity hash, it was never used as a key. | 12394 // If the object does not have an identity hash, it was never used as a key. |
| 11949 MaybeObject* maybe_hash = key->GetIdentityHash(OMIT_CREATION); | 12395 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); |
| 11950 if (maybe_hash->IsFailure()) return GetHeap()->undefined_value(); | 12396 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return false; |
| 12397 } |
| 12398 return (FindEntry(key) != kNotFound); |
| 12399 } |
| 12400 |
| 12401 |
| 12402 MaybeObject* ObjectHashSet::Add(Object* key) { |
| 12403 // Make sure the key object has an identity hash code. |
| 12404 int hash; |
| 12405 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); |
| 12406 if (maybe_hash->IsFailure()) return maybe_hash; |
| 12407 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); |
| 12408 } |
| 12409 int entry = FindEntry(key); |
| 12410 |
| 12411 // Check whether key is already present. |
| 12412 if (entry != kNotFound) return this; |
| 12413 |
| 12414 // Check whether the hash set should be extended and add entry. |
| 12415 Object* obj; |
| 12416 { MaybeObject* maybe_obj = EnsureCapacity(1, key); |
| 12417 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 12418 } |
| 12419 ObjectHashSet* table = ObjectHashSet::cast(obj); |
| 12420 entry = table->FindInsertionEntry(hash); |
| 12421 table->set(EntryToIndex(entry), key); |
| 12422 table->ElementAdded(); |
| 12423 return table; |
| 12424 } |
| 12425 |
| 12426 |
| 12427 MaybeObject* ObjectHashSet::Remove(Object* key) { |
| 12428 // If the object does not have an identity hash, it was never used as a key. |
| 12429 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); |
| 12430 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) return this; |
| 12431 } |
| 12432 int entry = FindEntry(key); |
| 12433 |
| 12434 // Check whether key is actually present. |
| 12435 if (entry == kNotFound) return this; |
| 12436 |
| 12437 // Remove entry and try to shrink this hash set. |
| 12438 set_null(EntryToIndex(entry)); |
| 12439 ElementRemoved(); |
| 12440 return Shrink(key); |
| 12441 } |
| 12442 |
| 12443 |
| 12444 Object* ObjectHashTable::Lookup(Object* key) { |
| 12445 // If the object does not have an identity hash, it was never used as a key. |
| 12446 { MaybeObject* maybe_hash = key->GetHash(OMIT_CREATION); |
| 12447 if (maybe_hash->ToObjectUnchecked()->IsUndefined()) { |
| 12448 return GetHeap()->undefined_value(); |
| 12449 } |
| 12450 } |
| 11951 int entry = FindEntry(key); | 12451 int entry = FindEntry(key); |
| 11952 if (entry == kNotFound) return GetHeap()->undefined_value(); | 12452 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 11953 return get(EntryToIndex(entry) + 1); | 12453 return get(EntryToIndex(entry) + 1); |
| 11954 } | 12454 } |
| 11955 | 12455 |
| 11956 | 12456 |
| 11957 MaybeObject* ObjectHashTable::Put(JSReceiver* key, Object* value) { | 12457 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) { |
| 11958 // Make sure the key object has an identity hash code. | 12458 // Make sure the key object has an identity hash code. |
| 11959 int hash; | 12459 int hash; |
| 11960 { MaybeObject* maybe_hash = key->GetIdentityHash(ALLOW_CREATION); | 12460 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); |
| 11961 if (maybe_hash->IsFailure()) return maybe_hash; | 12461 if (maybe_hash->IsFailure()) return maybe_hash; |
| 11962 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); | 12462 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); |
| 11963 } | 12463 } |
| 11964 int entry = FindEntry(key); | 12464 int entry = FindEntry(key); |
| 11965 | 12465 |
| 11966 // Check whether to perform removal operation. | 12466 // Check whether to perform removal operation. |
| 11967 if (value->IsUndefined()) { | 12467 if (value->IsUndefined()) { |
| 11968 if (entry == kNotFound) return this; | 12468 if (entry == kNotFound) return this; |
| 11969 RemoveEntry(entry); | 12469 RemoveEntry(entry); |
| 11970 return Shrink(key); | 12470 return Shrink(key); |
| 11971 } | 12471 } |
| 11972 | 12472 |
| 11973 // Key is already in table, just overwrite value. | 12473 // Key is already in table, just overwrite value. |
| 11974 if (entry != kNotFound) { | 12474 if (entry != kNotFound) { |
| 11975 set(EntryToIndex(entry) + 1, value); | 12475 set(EntryToIndex(entry) + 1, value); |
| 11976 return this; | 12476 return this; |
| 11977 } | 12477 } |
| 11978 | 12478 |
| 11979 // Check whether the hash table should be extended. | 12479 // Check whether the hash table should be extended. |
| 11980 Object* obj; | 12480 Object* obj; |
| 11981 { MaybeObject* maybe_obj = EnsureCapacity(1, key); | 12481 { MaybeObject* maybe_obj = EnsureCapacity(1, key); |
| 11982 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 12482 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11983 } | 12483 } |
| 11984 ObjectHashTable* table = ObjectHashTable::cast(obj); | 12484 ObjectHashTable* table = ObjectHashTable::cast(obj); |
| 11985 table->AddEntry(table->FindInsertionEntry(hash), key, value); | 12485 table->AddEntry(table->FindInsertionEntry(hash), key, value); |
| 11986 return table; | 12486 return table; |
| 11987 } | 12487 } |
| 11988 | 12488 |
| 11989 | 12489 |
| 11990 void ObjectHashTable::AddEntry(int entry, JSReceiver* key, Object* value) { | 12490 void ObjectHashTable::AddEntry(int entry, Object* key, Object* value) { |
| 11991 set(EntryToIndex(entry), key); | 12491 set(EntryToIndex(entry), key); |
| 11992 set(EntryToIndex(entry) + 1, value); | 12492 set(EntryToIndex(entry) + 1, value); |
| 11993 ElementAdded(); | 12493 ElementAdded(); |
| 11994 } | 12494 } |
| 11995 | 12495 |
| 11996 | 12496 |
| 11997 void ObjectHashTable::RemoveEntry(int entry, Heap* heap) { | 12497 void ObjectHashTable::RemoveEntry(int entry, Heap* heap) { |
| 11998 set_null(heap, EntryToIndex(entry)); | 12498 set_null(heap, EntryToIndex(entry)); |
| 11999 set_null(heap, EntryToIndex(entry) + 1); | 12499 set_null(heap, EntryToIndex(entry) + 1); |
| 12000 ElementRemoved(); | 12500 ElementRemoved(); |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12248 if (break_point_objects()->IsUndefined()) return 0; | 12748 if (break_point_objects()->IsUndefined()) return 0; |
| 12249 // Single break point. | 12749 // Single break point. |
| 12250 if (!break_point_objects()->IsFixedArray()) return 1; | 12750 if (!break_point_objects()->IsFixedArray()) return 1; |
| 12251 // Multiple break points. | 12751 // Multiple break points. |
| 12252 return FixedArray::cast(break_point_objects())->length(); | 12752 return FixedArray::cast(break_point_objects())->length(); |
| 12253 } | 12753 } |
| 12254 #endif // ENABLE_DEBUGGER_SUPPORT | 12754 #endif // ENABLE_DEBUGGER_SUPPORT |
| 12255 | 12755 |
| 12256 | 12756 |
| 12257 } } // namespace v8::internal | 12757 } } // namespace v8::internal |
| OLD | NEW |