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 |