| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 22 matching lines...) Expand all Loading... |
| 33 #include "api.h" | 33 #include "api.h" |
| 34 #include "arguments.h" | 34 #include "arguments.h" |
| 35 #include "codegen.h" | 35 #include "codegen.h" |
| 36 #include "compilation-cache.h" | 36 #include "compilation-cache.h" |
| 37 #include "compiler.h" | 37 #include "compiler.h" |
| 38 #include "cpu.h" | 38 #include "cpu.h" |
| 39 #include "dateparser-inl.h" | 39 #include "dateparser-inl.h" |
| 40 #include "debug.h" | 40 #include "debug.h" |
| 41 #include "deoptimizer.h" | 41 #include "deoptimizer.h" |
| 42 #include "execution.h" | 42 #include "execution.h" |
| 43 #include "global-handles.h" |
| 43 #include "jsregexp.h" | 44 #include "jsregexp.h" |
| 44 #include "liveedit.h" | 45 #include "liveedit.h" |
| 46 #include "liveobjectlist-inl.h" |
| 45 #include "parser.h" | 47 #include "parser.h" |
| 46 #include "platform.h" | 48 #include "platform.h" |
| 47 #include "runtime.h" | 49 #include "runtime.h" |
| 48 #include "runtime-profiler.h" | 50 #include "runtime-profiler.h" |
| 49 #include "scopeinfo.h" | 51 #include "scopeinfo.h" |
| 50 #include "smart-pointer.h" | 52 #include "smart-pointer.h" |
| 51 #include "stub-cache.h" | 53 #include "stub-cache.h" |
| 52 #include "v8threads.h" | 54 #include "v8threads.h" |
| 53 #include "string-search.h" | 55 #include "string-search.h" |
| 54 | 56 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 // an array. | 155 // an array. |
| 154 if (attributes != NONE) continue; | 156 if (attributes != NONE) continue; |
| 155 Object* value = | 157 Object* value = |
| 156 copy->GetProperty(key_string, &attributes)->ToObjectUnchecked(); | 158 copy->GetProperty(key_string, &attributes)->ToObjectUnchecked(); |
| 157 if (value->IsJSObject()) { | 159 if (value->IsJSObject()) { |
| 158 JSObject* js_object = JSObject::cast(value); | 160 JSObject* js_object = JSObject::cast(value); |
| 159 { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object); | 161 { MaybeObject* maybe_result = DeepCopyBoilerplate(js_object); |
| 160 if (!maybe_result->ToObject(&result)) return maybe_result; | 162 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 161 } | 163 } |
| 162 { MaybeObject* maybe_result = | 164 { MaybeObject* maybe_result = |
| 163 copy->SetProperty(key_string, result, NONE); | 165 // Creating object copy for literals. No strict mode needed. |
| 166 copy->SetProperty(key_string, result, NONE, kNonStrictMode); |
| 164 if (!maybe_result->ToObject(&result)) return maybe_result; | 167 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 165 } | 168 } |
| 166 } | 169 } |
| 167 } | 170 } |
| 168 } | 171 } |
| 169 | 172 |
| 170 // Deep copy local elements. | 173 // Deep copy local elements. |
| 171 // Pixel elements cannot be created using an object literal. | 174 // Pixel elements cannot be created using an object literal. |
| 172 ASSERT(!copy->HasPixelElements() && !copy->HasExternalArrayElements()); | 175 ASSERT(!copy->HasExternalArrayElements()); |
| 173 switch (copy->GetElementsKind()) { | 176 switch (copy->GetElementsKind()) { |
| 174 case JSObject::FAST_ELEMENTS: { | 177 case JSObject::FAST_ELEMENTS: { |
| 175 FixedArray* elements = FixedArray::cast(copy->elements()); | 178 FixedArray* elements = FixedArray::cast(copy->elements()); |
| 176 if (elements->map() == Heap::fixed_cow_array_map()) { | 179 if (elements->map() == Heap::fixed_cow_array_map()) { |
| 177 Counters::cow_arrays_created_runtime.Increment(); | 180 Counters::cow_arrays_created_runtime.Increment(); |
| 178 #ifdef DEBUG | 181 #ifdef DEBUG |
| 179 for (int i = 0; i < elements->length(); i++) { | 182 for (int i = 0; i < elements->length(); i++) { |
| 180 ASSERT(!elements->get(i)->IsJSObject()); | 183 ASSERT(!elements->get(i)->IsJSObject()); |
| 181 } | 184 } |
| 182 #endif | 185 #endif |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 // simple object literal. | 328 // simple object literal. |
| 326 Handle<FixedArray> array = Handle<FixedArray>::cast(value); | 329 Handle<FixedArray> array = Handle<FixedArray>::cast(value); |
| 327 value = CreateLiteralBoilerplate(literals, array); | 330 value = CreateLiteralBoilerplate(literals, array); |
| 328 if (value.is_null()) return value; | 331 if (value.is_null()) return value; |
| 329 } | 332 } |
| 330 Handle<Object> result; | 333 Handle<Object> result; |
| 331 uint32_t element_index = 0; | 334 uint32_t element_index = 0; |
| 332 if (key->IsSymbol()) { | 335 if (key->IsSymbol()) { |
| 333 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { | 336 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { |
| 334 // Array index as string (uint32). | 337 // Array index as string (uint32). |
| 335 result = SetOwnElement(boilerplate, element_index, value); | 338 result = SetOwnElement(boilerplate, |
| 339 element_index, |
| 340 value, |
| 341 kNonStrictMode); |
| 336 } else { | 342 } else { |
| 337 Handle<String> name(String::cast(*key)); | 343 Handle<String> name(String::cast(*key)); |
| 338 ASSERT(!name->AsArrayIndex(&element_index)); | 344 ASSERT(!name->AsArrayIndex(&element_index)); |
| 339 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, | 345 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, |
| 340 value, NONE); | 346 value, NONE); |
| 341 } | 347 } |
| 342 } else if (key->ToArrayIndex(&element_index)) { | 348 } else if (key->ToArrayIndex(&element_index)) { |
| 343 // Array index (uint32). | 349 // Array index (uint32). |
| 344 result = SetOwnElement(boilerplate, element_index, value); | 350 result = SetOwnElement(boilerplate, |
| 351 element_index, |
| 352 value, |
| 353 kNonStrictMode); |
| 345 } else { | 354 } else { |
| 346 // Non-uint32 number. | 355 // Non-uint32 number. |
| 347 ASSERT(key->IsNumber()); | 356 ASSERT(key->IsNumber()); |
| 348 double num = key->Number(); | 357 double num = key->Number(); |
| 349 char arr[100]; | 358 char arr[100]; |
| 350 Vector<char> buffer(arr, ARRAY_SIZE(arr)); | 359 Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
| 351 const char* str = DoubleToCString(num, buffer); | 360 const char* str = DoubleToCString(num, buffer); |
| 352 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); | 361 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); |
| 353 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, | 362 result = SetLocalPropertyIgnoreAttributes(boilerplate, name, |
| 354 value, NONE); | 363 value, NONE); |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 // Create a catch context extension object. | 548 // Create a catch context extension object. |
| 540 JSFunction* constructor = | 549 JSFunction* constructor = |
| 541 Top::context()->global_context()->context_extension_function(); | 550 Top::context()->global_context()->context_extension_function(); |
| 542 Object* object; | 551 Object* object; |
| 543 { MaybeObject* maybe_object = Heap::AllocateJSObject(constructor); | 552 { MaybeObject* maybe_object = Heap::AllocateJSObject(constructor); |
| 544 if (!maybe_object->ToObject(&object)) return maybe_object; | 553 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 545 } | 554 } |
| 546 // Assign the exception value to the catch variable and make sure | 555 // Assign the exception value to the catch variable and make sure |
| 547 // that the catch variable is DontDelete. | 556 // that the catch variable is DontDelete. |
| 548 { MaybeObject* maybe_value = | 557 { MaybeObject* maybe_value = |
| 549 JSObject::cast(object)->SetProperty(key, value, DONT_DELETE); | 558 // Passing non-strict per ECMA-262 5th Ed. 12.14. Catch, bullet #4. |
| 559 JSObject::cast(object)->SetProperty( |
| 560 key, value, DONT_DELETE, kNonStrictMode); |
| 550 if (!maybe_value->ToObject(&value)) return maybe_value; | 561 if (!maybe_value->ToObject(&value)) return maybe_value; |
| 551 } | 562 } |
| 552 return object; | 563 return object; |
| 553 } | 564 } |
| 554 | 565 |
| 555 | 566 |
| 556 static MaybeObject* Runtime_ClassOf(Arguments args) { | 567 static MaybeObject* Runtime_ClassOf(Arguments args) { |
| 557 NoHandleAllocation ha; | 568 NoHandleAllocation ha; |
| 558 ASSERT(args.length() == 1); | 569 ASSERT(args.length() == 1); |
| 559 Object* obj = args[0]; | 570 Object* obj = args[0]; |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 elms->set(VALUE_INDEX, *substr); | 787 elms->set(VALUE_INDEX, *substr); |
| 777 elms->set(WRITABLE_INDEX, Heap::false_value()); | 788 elms->set(WRITABLE_INDEX, Heap::false_value()); |
| 778 elms->set(ENUMERABLE_INDEX, Heap::false_value()); | 789 elms->set(ENUMERABLE_INDEX, Heap::false_value()); |
| 779 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); | 790 elms->set(CONFIGURABLE_INDEX, Heap::false_value()); |
| 780 return *desc; | 791 return *desc; |
| 781 } | 792 } |
| 782 | 793 |
| 783 case JSObject::INTERCEPTED_ELEMENT: | 794 case JSObject::INTERCEPTED_ELEMENT: |
| 784 case JSObject::FAST_ELEMENT: { | 795 case JSObject::FAST_ELEMENT: { |
| 785 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 796 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 786 elms->set(VALUE_INDEX, *GetElement(obj, index)); | 797 Handle<Object> value = GetElement(obj, index); |
| 798 RETURN_IF_EMPTY_HANDLE(value); |
| 799 elms->set(VALUE_INDEX, *value); |
| 787 elms->set(WRITABLE_INDEX, Heap::true_value()); | 800 elms->set(WRITABLE_INDEX, Heap::true_value()); |
| 788 elms->set(ENUMERABLE_INDEX, Heap::true_value()); | 801 elms->set(ENUMERABLE_INDEX, Heap::true_value()); |
| 789 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); | 802 elms->set(CONFIGURABLE_INDEX, Heap::true_value()); |
| 790 return *desc; | 803 return *desc; |
| 791 } | 804 } |
| 792 | 805 |
| 793 case JSObject::DICTIONARY_ELEMENT: { | 806 case JSObject::DICTIONARY_ELEMENT: { |
| 794 Handle<JSObject> holder = obj; | 807 Handle<JSObject> holder = obj; |
| 795 if (obj->IsJSGlobalProxy()) { | 808 if (obj->IsJSGlobalProxy()) { |
| 796 Object* proto = obj->GetPrototype(); | 809 Object* proto = obj->GetPrototype(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 809 FixedArray::cast(dictionary->ValueAt(entry)); | 822 FixedArray::cast(dictionary->ValueAt(entry)); |
| 810 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); | 823 elms->set(IS_ACCESSOR_INDEX, Heap::true_value()); |
| 811 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { | 824 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { |
| 812 elms->set(GETTER_INDEX, callbacks->get(0)); | 825 elms->set(GETTER_INDEX, callbacks->get(0)); |
| 813 } | 826 } |
| 814 if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { | 827 if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { |
| 815 elms->set(SETTER_INDEX, callbacks->get(1)); | 828 elms->set(SETTER_INDEX, callbacks->get(1)); |
| 816 } | 829 } |
| 817 break; | 830 break; |
| 818 } | 831 } |
| 819 case NORMAL: | 832 case NORMAL: { |
| 820 // This is a data property. | 833 // This is a data property. |
| 821 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); | 834 elms->set(IS_ACCESSOR_INDEX, Heap::false_value()); |
| 822 elms->set(VALUE_INDEX, *GetElement(obj, index)); | 835 Handle<Object> value = GetElement(obj, index); |
| 836 ASSERT(!value.is_null()); |
| 837 elms->set(VALUE_INDEX, *value); |
| 823 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); | 838 elms->set(WRITABLE_INDEX, Heap::ToBoolean(!details.IsReadOnly())); |
| 824 break; | 839 break; |
| 840 } |
| 825 default: | 841 default: |
| 826 UNREACHABLE(); | 842 UNREACHABLE(); |
| 827 break; | 843 break; |
| 828 } | 844 } |
| 829 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); | 845 elms->set(ENUMERABLE_INDEX, Heap::ToBoolean(!details.IsDontEnum())); |
| 830 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); | 846 elms->set(CONFIGURABLE_INDEX, Heap::ToBoolean(!details.IsDontDelete())); |
| 831 return *desc; | 847 return *desc; |
| 832 } | 848 } |
| 833 } | 849 } |
| 834 } | 850 } |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 987 HandleScope scope; | 1003 HandleScope scope; |
| 988 Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type)); | 1004 Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type)); |
| 989 Handle<Object> args[2] = { type_handle, name }; | 1005 Handle<Object> args[2] = { type_handle, name }; |
| 990 Handle<Object> error = | 1006 Handle<Object> error = |
| 991 Factory::NewTypeError("redeclaration", HandleVector(args, 2)); | 1007 Factory::NewTypeError("redeclaration", HandleVector(args, 2)); |
| 992 return Top::Throw(*error); | 1008 return Top::Throw(*error); |
| 993 } | 1009 } |
| 994 | 1010 |
| 995 | 1011 |
| 996 static MaybeObject* Runtime_DeclareGlobals(Arguments args) { | 1012 static MaybeObject* Runtime_DeclareGlobals(Arguments args) { |
| 1013 ASSERT(args.length() == 4); |
| 997 HandleScope scope; | 1014 HandleScope scope; |
| 998 Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global()); | 1015 Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global()); |
| 999 | 1016 |
| 1000 Handle<Context> context = args.at<Context>(0); | 1017 Handle<Context> context = args.at<Context>(0); |
| 1001 CONVERT_ARG_CHECKED(FixedArray, pairs, 1); | 1018 CONVERT_ARG_CHECKED(FixedArray, pairs, 1); |
| 1002 bool is_eval = Smi::cast(args[2])->value() == 1; | 1019 bool is_eval = Smi::cast(args[2])->value() == 1; |
| 1020 StrictModeFlag strict_mode = |
| 1021 static_cast<StrictModeFlag>(Smi::cast(args[3])->value()); |
| 1022 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); |
| 1003 | 1023 |
| 1004 // Compute the property attributes. According to ECMA-262, section | 1024 // Compute the property attributes. According to ECMA-262, section |
| 1005 // 13, page 71, the property must be read-only and | 1025 // 13, page 71, the property must be read-only and |
| 1006 // non-deletable. However, neither SpiderMonkey nor KJS creates the | 1026 // non-deletable. However, neither SpiderMonkey nor KJS creates the |
| 1007 // property as read-only, so we don't either. | 1027 // property as read-only, so we don't either. |
| 1008 PropertyAttributes base = is_eval ? NONE : DONT_DELETE; | 1028 PropertyAttributes base = is_eval ? NONE : DONT_DELETE; |
| 1009 | 1029 |
| 1010 // Traverse the name/value pairs and set the properties. | 1030 // Traverse the name/value pairs and set the properties. |
| 1011 int length = pairs->length(); | 1031 int length = pairs->length(); |
| 1012 for (int i = 0; i < length; i += 2) { | 1032 for (int i = 0; i < length; i += 2) { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 const char* type = (is_read_only) ? "const" : "var"; | 1064 const char* type = (is_read_only) ? "const" : "var"; |
| 1045 return ThrowRedeclarationError(type, name); | 1065 return ThrowRedeclarationError(type, name); |
| 1046 }; | 1066 }; |
| 1047 // The property already exists without conflicting: Go to | 1067 // The property already exists without conflicting: Go to |
| 1048 // the next declaration. | 1068 // the next declaration. |
| 1049 continue; | 1069 continue; |
| 1050 } | 1070 } |
| 1051 // Fall-through and introduce the absent property by using | 1071 // Fall-through and introduce the absent property by using |
| 1052 // SetProperty. | 1072 // SetProperty. |
| 1053 } else { | 1073 } else { |
| 1074 // For const properties, we treat a callback with this name |
| 1075 // even in the prototype as a conflicting declaration. |
| 1076 if (is_const_property && (lookup.type() == CALLBACKS)) { |
| 1077 return ThrowRedeclarationError("const", name); |
| 1078 } |
| 1079 // Otherwise, we check for locally conflicting declarations. |
| 1054 if (is_local && (is_read_only || is_const_property)) { | 1080 if (is_local && (is_read_only || is_const_property)) { |
| 1055 const char* type = (is_read_only) ? "const" : "var"; | 1081 const char* type = (is_read_only) ? "const" : "var"; |
| 1056 return ThrowRedeclarationError(type, name); | 1082 return ThrowRedeclarationError(type, name); |
| 1057 } | 1083 } |
| 1058 // The property already exists without conflicting: Go to | 1084 // The property already exists without conflicting: Go to |
| 1059 // the next declaration. | 1085 // the next declaration. |
| 1060 continue; | 1086 continue; |
| 1061 } | 1087 } |
| 1062 } | 1088 } |
| 1063 } else { | 1089 } else { |
| 1064 // Copy the function and update its context. Use it as value. | 1090 // Copy the function and update its context. Use it as value. |
| 1065 Handle<SharedFunctionInfo> shared = | 1091 Handle<SharedFunctionInfo> shared = |
| 1066 Handle<SharedFunctionInfo>::cast(value); | 1092 Handle<SharedFunctionInfo>::cast(value); |
| 1067 Handle<JSFunction> function = | 1093 Handle<JSFunction> function = |
| 1068 Factory::NewFunctionFromSharedFunctionInfo(shared, context, TENURED); | 1094 Factory::NewFunctionFromSharedFunctionInfo(shared, context, TENURED); |
| 1069 value = function; | 1095 value = function; |
| 1070 } | 1096 } |
| 1071 | 1097 |
| 1072 LookupResult lookup; | 1098 LookupResult lookup; |
| 1073 global->LocalLookup(*name, &lookup); | 1099 global->LocalLookup(*name, &lookup); |
| 1074 | 1100 |
| 1075 PropertyAttributes attributes = is_const_property | 1101 PropertyAttributes attributes = is_const_property |
| 1076 ? static_cast<PropertyAttributes>(base | READ_ONLY) | 1102 ? static_cast<PropertyAttributes>(base | READ_ONLY) |
| 1077 : base; | 1103 : base; |
| 1078 | 1104 |
| 1079 if (lookup.IsProperty()) { | 1105 // There's a local property that we need to overwrite because |
| 1080 // There's a local property that we need to overwrite because | 1106 // we're either declaring a function or there's an interceptor |
| 1081 // we're either declaring a function or there's an interceptor | 1107 // that claims the property is absent. |
| 1082 // that claims the property is absent. | 1108 // |
| 1109 // Check for conflicting re-declarations. We cannot have |
| 1110 // conflicting types in case of intercepted properties because |
| 1111 // they are absent. |
| 1112 if (lookup.IsProperty() && |
| 1113 (lookup.type() != INTERCEPTOR) && |
| 1114 (lookup.IsReadOnly() || is_const_property)) { |
| 1115 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; |
| 1116 return ThrowRedeclarationError(type, name); |
| 1117 } |
| 1083 | 1118 |
| 1084 // Check for conflicting re-declarations. We cannot have | 1119 // Safari does not allow the invocation of callback setters for |
| 1085 // conflicting types in case of intercepted properties because | 1120 // function declarations. To mimic this behavior, we do not allow |
| 1086 // they are absent. | 1121 // the invocation of setters for function values. This makes a |
| 1087 if (lookup.type() != INTERCEPTOR && | 1122 // difference for global functions with the same names as event |
| 1088 (lookup.IsReadOnly() || is_const_property)) { | 1123 // handlers such as "function onload() {}". Firefox does call the |
| 1089 const char* type = (lookup.IsReadOnly()) ? "const" : "var"; | 1124 // onload setter in those case and Safari does not. We follow |
| 1090 return ThrowRedeclarationError(type, name); | 1125 // Safari for compatibility. |
| 1126 if (value->IsJSFunction()) { |
| 1127 // Do not change DONT_DELETE to false from true. |
| 1128 if (lookup.IsProperty() && (lookup.type() != INTERCEPTOR)) { |
| 1129 attributes = static_cast<PropertyAttributes>( |
| 1130 attributes | (lookup.GetAttributes() & DONT_DELETE)); |
| 1091 } | 1131 } |
| 1092 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes)); | 1132 RETURN_IF_EMPTY_HANDLE(SetLocalPropertyIgnoreAttributes(global, |
| 1133 name, |
| 1134 value, |
| 1135 attributes)); |
| 1093 } else { | 1136 } else { |
| 1094 // If a property with this name does not already exist on the | 1137 RETURN_IF_EMPTY_HANDLE(SetProperty(global, |
| 1095 // global object add the property locally. We take special | 1138 name, |
| 1096 // precautions to always add it as a local property even in case | 1139 value, |
| 1097 // of callbacks in the prototype chain (this rules out using | 1140 attributes, |
| 1098 // SetProperty). Also, we must use the handle-based version to | 1141 strict_mode)); |
| 1099 // avoid GC issues. | |
| 1100 RETURN_IF_EMPTY_HANDLE( | |
| 1101 SetLocalPropertyIgnoreAttributes(global, name, value, attributes)); | |
| 1102 } | 1142 } |
| 1103 } | 1143 } |
| 1104 | 1144 |
| 1105 ASSERT(!Top::has_pending_exception()); | 1145 ASSERT(!Top::has_pending_exception()); |
| 1106 return Heap::undefined_value(); | 1146 return Heap::undefined_value(); |
| 1107 } | 1147 } |
| 1108 | 1148 |
| 1109 | 1149 |
| 1110 static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { | 1150 static MaybeObject* Runtime_DeclareContextSlot(Arguments args) { |
| 1111 HandleScope scope; | 1151 HandleScope scope; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1145 // the function context or the arguments object. | 1185 // the function context or the arguments object. |
| 1146 if (holder->IsContext()) { | 1186 if (holder->IsContext()) { |
| 1147 ASSERT(holder.is_identical_to(context)); | 1187 ASSERT(holder.is_identical_to(context)); |
| 1148 if (((attributes & READ_ONLY) == 0) || | 1188 if (((attributes & READ_ONLY) == 0) || |
| 1149 context->get(index)->IsTheHole()) { | 1189 context->get(index)->IsTheHole()) { |
| 1150 context->set(index, *initial_value); | 1190 context->set(index, *initial_value); |
| 1151 } | 1191 } |
| 1152 } else { | 1192 } else { |
| 1153 // The holder is an arguments object. | 1193 // The holder is an arguments object. |
| 1154 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | 1194 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); |
| 1155 Handle<Object> result = SetElement(arguments, index, initial_value); | 1195 Handle<Object> result = SetElement(arguments, index, initial_value, |
| 1196 kNonStrictMode); |
| 1156 if (result.is_null()) return Failure::Exception(); | 1197 if (result.is_null()) return Failure::Exception(); |
| 1157 } | 1198 } |
| 1158 } else { | 1199 } else { |
| 1159 // Slow case: The property is not in the FixedArray part of the context. | 1200 // Slow case: The property is not in the FixedArray part of the context. |
| 1160 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1201 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
| 1161 RETURN_IF_EMPTY_HANDLE( | 1202 RETURN_IF_EMPTY_HANDLE( |
| 1162 SetProperty(context_ext, name, initial_value, mode)); | 1203 SetProperty(context_ext, name, initial_value, |
| 1204 mode, kNonStrictMode)); |
| 1163 } | 1205 } |
| 1164 } | 1206 } |
| 1165 | 1207 |
| 1166 } else { | 1208 } else { |
| 1167 // The property is not in the function context. It needs to be | 1209 // The property is not in the function context. It needs to be |
| 1168 // "declared" in the function context's extension context, or in the | 1210 // "declared" in the function context's extension context, or in the |
| 1169 // global context. | 1211 // global context. |
| 1170 Handle<JSObject> context_ext; | 1212 Handle<JSObject> context_ext; |
| 1171 if (context->has_extension()) { | 1213 if (context->has_extension()) { |
| 1172 // The function context's extension context exists - use it. | 1214 // The function context's extension context exists - use it. |
| 1173 context_ext = Handle<JSObject>(context->extension()); | 1215 context_ext = Handle<JSObject>(context->extension()); |
| 1174 } else { | 1216 } else { |
| 1175 // The function context's extension context does not exists - allocate | 1217 // The function context's extension context does not exists - allocate |
| 1176 // it. | 1218 // it. |
| 1177 context_ext = Factory::NewJSObject(Top::context_extension_function()); | 1219 context_ext = Factory::NewJSObject(Top::context_extension_function()); |
| 1178 // And store it in the extension slot. | 1220 // And store it in the extension slot. |
| 1179 context->set_extension(*context_ext); | 1221 context->set_extension(*context_ext); |
| 1180 } | 1222 } |
| 1181 ASSERT(*context_ext != NULL); | 1223 ASSERT(*context_ext != NULL); |
| 1182 | 1224 |
| 1183 // Declare the property by setting it to the initial value if provided, | 1225 // Declare the property by setting it to the initial value if provided, |
| 1184 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for | 1226 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for |
| 1185 // constant declarations). | 1227 // constant declarations). |
| 1186 ASSERT(!context_ext->HasLocalProperty(*name)); | 1228 ASSERT(!context_ext->HasLocalProperty(*name)); |
| 1187 Handle<Object> value(Heap::undefined_value()); | 1229 Handle<Object> value(Heap::undefined_value()); |
| 1188 if (*initial_value != NULL) value = initial_value; | 1230 if (*initial_value != NULL) value = initial_value; |
| 1189 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode)); | 1231 // Declaring a const context slot is a conflicting declaration if |
| 1232 // there is a callback with that name in a prototype. It is |
| 1233 // allowed to introduce const variables in |
| 1234 // JSContextExtensionObjects. They are treated specially in |
| 1235 // SetProperty and no setters are invoked for those since they are |
| 1236 // not real JSObjects. |
| 1237 if (initial_value->IsTheHole() && |
| 1238 !context_ext->IsJSContextExtensionObject()) { |
| 1239 LookupResult lookup; |
| 1240 context_ext->Lookup(*name, &lookup); |
| 1241 if (lookup.IsProperty() && (lookup.type() == CALLBACKS)) { |
| 1242 return ThrowRedeclarationError("const", name); |
| 1243 } |
| 1244 } |
| 1245 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, mode, |
| 1246 kNonStrictMode)); |
| 1190 } | 1247 } |
| 1191 | 1248 |
| 1192 return Heap::undefined_value(); | 1249 return Heap::undefined_value(); |
| 1193 } | 1250 } |
| 1194 | 1251 |
| 1195 | 1252 |
| 1196 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { | 1253 static MaybeObject* Runtime_InitializeVarGlobal(Arguments args) { |
| 1197 NoHandleAllocation nha; | 1254 NoHandleAllocation nha; |
| 1255 // args[0] == name |
| 1256 // args[1] == strict_mode |
| 1257 // args[2] == value (optional) |
| 1198 | 1258 |
| 1199 // Determine if we need to assign to the variable if it already | 1259 // Determine if we need to assign to the variable if it already |
| 1200 // exists (based on the number of arguments). | 1260 // exists (based on the number of arguments). |
| 1201 RUNTIME_ASSERT(args.length() == 1 || args.length() == 2); | 1261 RUNTIME_ASSERT(args.length() == 2 || args.length() == 3); |
| 1202 bool assign = args.length() == 2; | 1262 bool assign = args.length() == 3; |
| 1203 | 1263 |
| 1204 CONVERT_ARG_CHECKED(String, name, 0); | 1264 CONVERT_ARG_CHECKED(String, name, 0); |
| 1205 GlobalObject* global = Top::context()->global(); | 1265 GlobalObject* global = Top::context()->global(); |
| 1266 RUNTIME_ASSERT(args[1]->IsSmi()); |
| 1267 StrictModeFlag strict_mode = |
| 1268 static_cast<StrictModeFlag>(Smi::cast(args[1])->value()); |
| 1269 ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); |
| 1206 | 1270 |
| 1207 // According to ECMA-262, section 12.2, page 62, the property must | 1271 // According to ECMA-262, section 12.2, page 62, the property must |
| 1208 // not be deletable. | 1272 // not be deletable. |
| 1209 PropertyAttributes attributes = DONT_DELETE; | 1273 PropertyAttributes attributes = DONT_DELETE; |
| 1210 | 1274 |
| 1211 // Lookup the property locally in the global object. If it isn't | 1275 // Lookup the property locally in the global object. If it isn't |
| 1212 // there, there is a property with this name in the prototype chain. | 1276 // there, there is a property with this name in the prototype chain. |
| 1213 // We follow Safari and Firefox behavior and only set the property | 1277 // We follow Safari and Firefox behavior and only set the property |
| 1214 // locally if there is an explicit initialization value that we have | 1278 // locally if there is an explicit initialization value that we have |
| 1215 // to assign to the property. When adding the property we take | 1279 // to assign to the property. |
| 1216 // special precautions to always add it as a local property even in | |
| 1217 // case of callbacks in the prototype chain (this rules out using | |
| 1218 // SetProperty). We have SetLocalPropertyIgnoreAttributes for | |
| 1219 // this. | |
| 1220 // Note that objects can have hidden prototypes, so we need to traverse | 1280 // Note that objects can have hidden prototypes, so we need to traverse |
| 1221 // the whole chain of hidden prototypes to do a 'local' lookup. | 1281 // the whole chain of hidden prototypes to do a 'local' lookup. |
| 1222 JSObject* real_holder = global; | 1282 JSObject* real_holder = global; |
| 1223 LookupResult lookup; | 1283 LookupResult lookup; |
| 1224 while (true) { | 1284 while (true) { |
| 1225 real_holder->LocalLookup(*name, &lookup); | 1285 real_holder->LocalLookup(*name, &lookup); |
| 1226 if (lookup.IsProperty()) { | 1286 if (lookup.IsProperty()) { |
| 1227 // Determine if this is a redeclaration of something read-only. | 1287 // Determine if this is a redeclaration of something read-only. |
| 1228 if (lookup.IsReadOnly()) { | 1288 if (lookup.IsReadOnly()) { |
| 1229 // If we found readonly property on one of hidden prototypes, | 1289 // If we found readonly property on one of hidden prototypes, |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1255 } | 1315 } |
| 1256 } | 1316 } |
| 1257 | 1317 |
| 1258 if (found && !assign) { | 1318 if (found && !assign) { |
| 1259 // The global property is there and we're not assigning any value | 1319 // The global property is there and we're not assigning any value |
| 1260 // to it. Just return. | 1320 // to it. Just return. |
| 1261 return Heap::undefined_value(); | 1321 return Heap::undefined_value(); |
| 1262 } | 1322 } |
| 1263 | 1323 |
| 1264 // Assign the value (or undefined) to the property. | 1324 // Assign the value (or undefined) to the property. |
| 1265 Object* value = (assign) ? args[1] : Heap::undefined_value(); | 1325 Object* value = (assign) ? args[2] : Heap::undefined_value(); |
| 1266 return real_holder->SetProperty(&lookup, *name, value, attributes); | 1326 return real_holder->SetProperty( |
| 1327 &lookup, *name, value, attributes, strict_mode); |
| 1267 } | 1328 } |
| 1268 | 1329 |
| 1269 Object* proto = real_holder->GetPrototype(); | 1330 Object* proto = real_holder->GetPrototype(); |
| 1270 if (!proto->IsJSObject()) | 1331 if (!proto->IsJSObject()) |
| 1271 break; | 1332 break; |
| 1272 | 1333 |
| 1273 if (!JSObject::cast(proto)->map()->is_hidden_prototype()) | 1334 if (!JSObject::cast(proto)->map()->is_hidden_prototype()) |
| 1274 break; | 1335 break; |
| 1275 | 1336 |
| 1276 real_holder = JSObject::cast(proto); | 1337 real_holder = JSObject::cast(proto); |
| 1277 } | 1338 } |
| 1278 | 1339 |
| 1279 global = Top::context()->global(); | 1340 global = Top::context()->global(); |
| 1280 if (assign) { | 1341 if (assign) { |
| 1281 return global->SetLocalPropertyIgnoreAttributes(*name, | 1342 return global->SetProperty(*name, args[2], attributes, strict_mode); |
| 1282 args[1], | |
| 1283 attributes); | |
| 1284 } | 1343 } |
| 1285 return Heap::undefined_value(); | 1344 return Heap::undefined_value(); |
| 1286 } | 1345 } |
| 1287 | 1346 |
| 1288 | 1347 |
| 1289 static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) { | 1348 static MaybeObject* Runtime_InitializeConstGlobal(Arguments args) { |
| 1290 // All constants are declared with an initial value. The name | 1349 // All constants are declared with an initial value. The name |
| 1291 // of the constant is the first argument and the initial value | 1350 // of the constant is the first argument and the initial value |
| 1292 // is the second. | 1351 // is the second. |
| 1293 RUNTIME_ASSERT(args.length() == 2); | 1352 RUNTIME_ASSERT(args.length() == 2); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 | 1392 |
| 1334 // Restore global object from context (in case of GC) and continue | 1393 // Restore global object from context (in case of GC) and continue |
| 1335 // with setting the value because the property is either absent or | 1394 // with setting the value because the property is either absent or |
| 1336 // read-only. We also have to do redo the lookup. | 1395 // read-only. We also have to do redo the lookup. |
| 1337 HandleScope handle_scope; | 1396 HandleScope handle_scope; |
| 1338 Handle<GlobalObject> global(Top::context()->global()); | 1397 Handle<GlobalObject> global(Top::context()->global()); |
| 1339 | 1398 |
| 1340 // BUG 1213575: Handle the case where we have to set a read-only | 1399 // BUG 1213575: Handle the case where we have to set a read-only |
| 1341 // property through an interceptor and only do it if it's | 1400 // property through an interceptor and only do it if it's |
| 1342 // uninitialized, e.g. the hole. Nirk... | 1401 // uninitialized, e.g. the hole. Nirk... |
| 1343 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, attributes)); | 1402 // Passing non-strict mode because the property is writable. |
| 1403 RETURN_IF_EMPTY_HANDLE(SetProperty(global, |
| 1404 name, |
| 1405 value, |
| 1406 attributes, |
| 1407 kNonStrictMode)); |
| 1344 return *value; | 1408 return *value; |
| 1345 } | 1409 } |
| 1346 | 1410 |
| 1347 // Set the value, but only we're assigning the initial value to a | 1411 // Set the value, but only we're assigning the initial value to a |
| 1348 // constant. For now, we determine this by checking if the | 1412 // constant. For now, we determine this by checking if the |
| 1349 // current value is the hole. | 1413 // current value is the hole. |
| 1414 // Strict mode handling not needed (const disallowed in strict mode). |
| 1350 PropertyType type = lookup.type(); | 1415 PropertyType type = lookup.type(); |
| 1351 if (type == FIELD) { | 1416 if (type == FIELD) { |
| 1352 FixedArray* properties = global->properties(); | 1417 FixedArray* properties = global->properties(); |
| 1353 int index = lookup.GetFieldIndex(); | 1418 int index = lookup.GetFieldIndex(); |
| 1354 if (properties->get(index)->IsTheHole()) { | 1419 if (properties->get(index)->IsTheHole()) { |
| 1355 properties->set(index, *value); | 1420 properties->set(index, *value); |
| 1356 } | 1421 } |
| 1357 } else if (type == NORMAL) { | 1422 } else if (type == NORMAL) { |
| 1358 if (global->GetNormalizedProperty(&lookup)->IsTheHole()) { | 1423 if (global->GetNormalizedProperty(&lookup)->IsTheHole()) { |
| 1359 global->SetNormalizedProperty(&lookup, *value); | 1424 global->SetNormalizedProperty(&lookup, *value); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1406 // should have been a const redeclaration error when declaring | 1471 // should have been a const redeclaration error when declaring |
| 1407 // the const property. | 1472 // the const property. |
| 1408 ASSERT(!holder.is_identical_to(context)); | 1473 ASSERT(!holder.is_identical_to(context)); |
| 1409 if ((attributes & READ_ONLY) == 0) { | 1474 if ((attributes & READ_ONLY) == 0) { |
| 1410 Handle<Context>::cast(holder)->set(index, *value); | 1475 Handle<Context>::cast(holder)->set(index, *value); |
| 1411 } | 1476 } |
| 1412 } else { | 1477 } else { |
| 1413 // The holder is an arguments object. | 1478 // The holder is an arguments object. |
| 1414 ASSERT((attributes & READ_ONLY) == 0); | 1479 ASSERT((attributes & READ_ONLY) == 0); |
| 1415 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); | 1480 Handle<JSObject> arguments(Handle<JSObject>::cast(holder)); |
| 1416 SetElement(arguments, index, value); | 1481 RETURN_IF_EMPTY_HANDLE( |
| 1482 SetElement(arguments, index, value, kNonStrictMode)); |
| 1417 } | 1483 } |
| 1418 return *value; | 1484 return *value; |
| 1419 } | 1485 } |
| 1420 | 1486 |
| 1421 // The property could not be found, we introduce it in the global | 1487 // The property could not be found, we introduce it in the global |
| 1422 // context. | 1488 // context. |
| 1423 if (attributes == ABSENT) { | 1489 if (attributes == ABSENT) { |
| 1424 Handle<JSObject> global = Handle<JSObject>(Top::context()->global()); | 1490 Handle<JSObject> global = Handle<JSObject>(Top::context()->global()); |
| 1425 RETURN_IF_EMPTY_HANDLE(SetProperty(global, name, value, NONE)); | 1491 // Strict mode not needed (const disallowed in strict mode). |
| 1492 RETURN_IF_EMPTY_HANDLE( |
| 1493 SetProperty(global, name, value, NONE, kNonStrictMode)); |
| 1426 return *value; | 1494 return *value; |
| 1427 } | 1495 } |
| 1428 | 1496 |
| 1429 // The property was present in a context extension object. | 1497 // The property was present in a context extension object. |
| 1430 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); | 1498 Handle<JSObject> context_ext = Handle<JSObject>::cast(holder); |
| 1431 | 1499 |
| 1432 if (*context_ext == context->extension()) { | 1500 if (*context_ext == context->extension()) { |
| 1433 // This is the property that was introduced by the const | 1501 // This is the property that was introduced by the const |
| 1434 // declaration. Set it if it hasn't been set before. NOTE: We | 1502 // declaration. Set it if it hasn't been set before. NOTE: We |
| 1435 // cannot use GetProperty() to get the current value as it | 1503 // cannot use GetProperty() to get the current value as it |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1452 } | 1520 } |
| 1453 } else { | 1521 } else { |
| 1454 // We should not reach here. Any real, named property should be | 1522 // We should not reach here. Any real, named property should be |
| 1455 // either a field or a dictionary slot. | 1523 // either a field or a dictionary slot. |
| 1456 UNREACHABLE(); | 1524 UNREACHABLE(); |
| 1457 } | 1525 } |
| 1458 } else { | 1526 } else { |
| 1459 // The property was found in a different context extension object. | 1527 // The property was found in a different context extension object. |
| 1460 // Set it if it is not a read-only property. | 1528 // Set it if it is not a read-only property. |
| 1461 if ((attributes & READ_ONLY) == 0) { | 1529 if ((attributes & READ_ONLY) == 0) { |
| 1530 // Strict mode not needed (const disallowed in strict mode). |
| 1462 RETURN_IF_EMPTY_HANDLE( | 1531 RETURN_IF_EMPTY_HANDLE( |
| 1463 SetProperty(context_ext, name, value, attributes)); | 1532 SetProperty(context_ext, name, value, attributes, kNonStrictMode)); |
| 1464 } | 1533 } |
| 1465 } | 1534 } |
| 1466 | 1535 |
| 1467 return *value; | 1536 return *value; |
| 1468 } | 1537 } |
| 1469 | 1538 |
| 1470 | 1539 |
| 1471 static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties( | 1540 static MaybeObject* Runtime_OptimizeObjectForAddingMultipleProperties( |
| 1472 Arguments args) { | 1541 Arguments args) { |
| 1473 HandleScope scope; | 1542 HandleScope scope; |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 const char* name, | 1688 const char* name, |
| 1620 Builtins::Name builtin_name) { | 1689 Builtins::Name builtin_name) { |
| 1621 Handle<String> key = Factory::LookupAsciiSymbol(name); | 1690 Handle<String> key = Factory::LookupAsciiSymbol(name); |
| 1622 Handle<Code> code(Builtins::builtin(builtin_name)); | 1691 Handle<Code> code(Builtins::builtin(builtin_name)); |
| 1623 Handle<JSFunction> optimized = Factory::NewFunction(key, | 1692 Handle<JSFunction> optimized = Factory::NewFunction(key, |
| 1624 JS_OBJECT_TYPE, | 1693 JS_OBJECT_TYPE, |
| 1625 JSObject::kHeaderSize, | 1694 JSObject::kHeaderSize, |
| 1626 code, | 1695 code, |
| 1627 false); | 1696 false); |
| 1628 optimized->shared()->DontAdaptArguments(); | 1697 optimized->shared()->DontAdaptArguments(); |
| 1629 SetProperty(holder, key, optimized, NONE); | 1698 SetProperty(holder, key, optimized, NONE, kStrictMode); |
| 1630 return optimized; | 1699 return optimized; |
| 1631 } | 1700 } |
| 1632 | 1701 |
| 1633 | 1702 |
| 1634 static MaybeObject* Runtime_SpecialArrayFunctions(Arguments args) { | 1703 static MaybeObject* Runtime_SpecialArrayFunctions(Arguments args) { |
| 1635 HandleScope scope; | 1704 HandleScope scope; |
| 1636 ASSERT(args.length() == 1); | 1705 ASSERT(args.length() == 1); |
| 1637 CONVERT_ARG_CHECKED(JSObject, holder, 0); | 1706 CONVERT_ARG_CHECKED(JSObject, holder, 0); |
| 1638 | 1707 |
| 1639 InstallBuiltin(holder, "pop", Builtins::ArrayPop); | 1708 InstallBuiltin(holder, "pop", Builtins::ArrayPop); |
| (...skipping 2026 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3666 uint32_t index; | 3735 uint32_t index; |
| 3667 bool is_element = name->AsArrayIndex(&index); | 3736 bool is_element = name->AsArrayIndex(&index); |
| 3668 | 3737 |
| 3669 // Special case for elements if any of the flags are true. | 3738 // Special case for elements if any of the flags are true. |
| 3670 // If elements are in fast case we always implicitly assume that: | 3739 // If elements are in fast case we always implicitly assume that: |
| 3671 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false. | 3740 // DONT_DELETE: false, DONT_ENUM: false, READ_ONLY: false. |
| 3672 if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) && | 3741 if (((unchecked & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) && |
| 3673 is_element) { | 3742 is_element) { |
| 3674 // Normalize the elements to enable attributes on the property. | 3743 // Normalize the elements to enable attributes on the property. |
| 3675 if (js_object->IsJSGlobalProxy()) { | 3744 if (js_object->IsJSGlobalProxy()) { |
| 3745 // We do not need to do access checks here since these has already |
| 3746 // been performed by the call to GetOwnProperty. |
| 3676 Handle<Object> proto(js_object->GetPrototype()); | 3747 Handle<Object> proto(js_object->GetPrototype()); |
| 3677 // If proxy is detached, ignore the assignment. Alternatively, | 3748 // If proxy is detached, ignore the assignment. Alternatively, |
| 3678 // we could throw an exception. | 3749 // we could throw an exception. |
| 3679 if (proto->IsNull()) return *obj_value; | 3750 if (proto->IsNull()) return *obj_value; |
| 3680 js_object = Handle<JSObject>::cast(proto); | 3751 js_object = Handle<JSObject>::cast(proto); |
| 3681 } | 3752 } |
| 3682 NormalizeElements(js_object); | 3753 NormalizeElements(js_object); |
| 3683 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); | 3754 Handle<NumberDictionary> dictionary(js_object->element_dictionary()); |
| 3684 // Make sure that we never go back to fast case. | 3755 // Make sure that we never go back to fast case. |
| 3685 dictionary->set_requires_slow_elements(); | 3756 dictionary->set_requires_slow_elements(); |
| 3686 PropertyDetails details = PropertyDetails(attr, NORMAL); | 3757 PropertyDetails details = PropertyDetails(attr, NORMAL); |
| 3687 NumberDictionarySet(dictionary, index, obj_value, details); | 3758 NumberDictionarySet(dictionary, index, obj_value, details); |
| 3688 return *obj_value; | 3759 return *obj_value; |
| 3689 } | 3760 } |
| 3690 | 3761 |
| 3691 LookupResult result; | 3762 LookupResult result; |
| 3692 js_object->LookupRealNamedProperty(*name, &result); | 3763 js_object->LookupRealNamedProperty(*name, &result); |
| 3693 | 3764 |
| 3765 // To be compatible with safari we do not change the value on API objects |
| 3766 // in defineProperty. Firefox disagrees here, and actually changes the value. |
| 3767 if (result.IsProperty() && |
| 3768 (result.type() == CALLBACKS) && |
| 3769 result.GetCallbackObject()->IsAccessorInfo()) { |
| 3770 return Heap::undefined_value(); |
| 3771 } |
| 3772 |
| 3694 // Take special care when attributes are different and there is already | 3773 // Take special care when attributes are different and there is already |
| 3695 // a property. For simplicity we normalize the property which enables us | 3774 // a property. For simplicity we normalize the property which enables us |
| 3696 // to not worry about changing the instance_descriptor and creating a new | 3775 // to not worry about changing the instance_descriptor and creating a new |
| 3697 // map. The current version of SetObjectProperty does not handle attributes | 3776 // map. The current version of SetObjectProperty does not handle attributes |
| 3698 // correctly in the case where a property is a field and is reset with | 3777 // correctly in the case where a property is a field and is reset with |
| 3699 // new attributes. | 3778 // new attributes. |
| 3700 if (result.IsProperty() && | 3779 if (result.IsProperty() && |
| 3701 (attr != result.GetAttributes() || result.type() == CALLBACKS)) { | 3780 (attr != result.GetAttributes() || result.type() == CALLBACKS)) { |
| 3702 // New attributes - normalize to avoid writing to instance descriptor | 3781 // New attributes - normalize to avoid writing to instance descriptor |
| 3703 if (js_object->IsJSGlobalProxy()) { | 3782 if (js_object->IsJSGlobalProxy()) { |
| 3704 // Since the result is a property, the prototype will exist so | 3783 // Since the result is a property, the prototype will exist so |
| 3705 // we don't have to check for null. | 3784 // we don't have to check for null. |
| 3706 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); | 3785 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); |
| 3707 } | 3786 } |
| 3708 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); | 3787 NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 3709 // Use IgnoreAttributes version since a readonly property may be | 3788 // Use IgnoreAttributes version since a readonly property may be |
| 3710 // overridden and SetProperty does not allow this. | 3789 // overridden and SetProperty does not allow this. |
| 3711 return js_object->SetLocalPropertyIgnoreAttributes(*name, | 3790 return js_object->SetLocalPropertyIgnoreAttributes(*name, |
| 3712 *obj_value, | 3791 *obj_value, |
| 3713 attr); | 3792 attr); |
| 3714 } | 3793 } |
| 3715 | 3794 |
| 3716 return Runtime::ForceSetObjectProperty(js_object, name, obj_value, attr); | 3795 return Runtime::ForceSetObjectProperty(js_object, name, obj_value, attr); |
| 3717 } | 3796 } |
| 3718 | 3797 |
| 3719 | 3798 |
| 3720 MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, | 3799 MaybeObject* Runtime::SetObjectProperty(Handle<Object> object, |
| 3721 Handle<Object> key, | 3800 Handle<Object> key, |
| 3722 Handle<Object> value, | 3801 Handle<Object> value, |
| 3723 PropertyAttributes attr) { | 3802 PropertyAttributes attr, |
| 3803 StrictModeFlag strict_mode) { |
| 3724 HandleScope scope; | 3804 HandleScope scope; |
| 3725 | 3805 |
| 3726 if (object->IsUndefined() || object->IsNull()) { | 3806 if (object->IsUndefined() || object->IsNull()) { |
| 3727 Handle<Object> args[2] = { key, object }; | 3807 Handle<Object> args[2] = { key, object }; |
| 3728 Handle<Object> error = | 3808 Handle<Object> error = |
| 3729 Factory::NewTypeError("non_object_property_store", | 3809 Factory::NewTypeError("non_object_property_store", |
| 3730 HandleVector(args, 2)); | 3810 HandleVector(args, 2)); |
| 3731 return Top::Throw(*error); | 3811 return Top::Throw(*error); |
| 3732 } | 3812 } |
| 3733 | 3813 |
| 3734 // If the object isn't a JavaScript object, we ignore the store. | 3814 // If the object isn't a JavaScript object, we ignore the store. |
| 3735 if (!object->IsJSObject()) return *value; | 3815 if (!object->IsJSObject()) return *value; |
| 3736 | 3816 |
| 3737 Handle<JSObject> js_object = Handle<JSObject>::cast(object); | 3817 Handle<JSObject> js_object = Handle<JSObject>::cast(object); |
| 3738 | 3818 |
| 3739 // Check if the given key is an array index. | 3819 // Check if the given key is an array index. |
| 3740 uint32_t index; | 3820 uint32_t index; |
| 3741 if (key->ToArrayIndex(&index)) { | 3821 if (key->ToArrayIndex(&index)) { |
| 3742 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters | 3822 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters |
| 3743 // of a string using [] notation. We need to support this too in | 3823 // of a string using [] notation. We need to support this too in |
| 3744 // JavaScript. | 3824 // JavaScript. |
| 3745 // In the case of a String object we just need to redirect the assignment to | 3825 // In the case of a String object we just need to redirect the assignment to |
| 3746 // the underlying string if the index is in range. Since the underlying | 3826 // the underlying string if the index is in range. Since the underlying |
| 3747 // string does nothing with the assignment then we can ignore such | 3827 // string does nothing with the assignment then we can ignore such |
| 3748 // assignments. | 3828 // assignments. |
| 3749 if (js_object->IsStringObjectWithCharacterAt(index)) { | 3829 if (js_object->IsStringObjectWithCharacterAt(index)) { |
| 3750 return *value; | 3830 return *value; |
| 3751 } | 3831 } |
| 3752 | 3832 |
| 3753 Handle<Object> result = SetElement(js_object, index, value); | 3833 Handle<Object> result = SetElement(js_object, index, value, strict_mode); |
| 3754 if (result.is_null()) return Failure::Exception(); | 3834 if (result.is_null()) return Failure::Exception(); |
| 3755 return *value; | 3835 return *value; |
| 3756 } | 3836 } |
| 3757 | 3837 |
| 3758 if (key->IsString()) { | 3838 if (key->IsString()) { |
| 3759 Handle<Object> result; | 3839 Handle<Object> result; |
| 3760 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 3840 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 3761 result = SetElement(js_object, index, value); | 3841 result = SetElement(js_object, index, value, strict_mode); |
| 3762 } else { | 3842 } else { |
| 3763 Handle<String> key_string = Handle<String>::cast(key); | 3843 Handle<String> key_string = Handle<String>::cast(key); |
| 3764 key_string->TryFlatten(); | 3844 key_string->TryFlatten(); |
| 3765 result = SetProperty(js_object, key_string, value, attr); | 3845 result = SetProperty(js_object, key_string, value, attr, strict_mode); |
| 3766 } | 3846 } |
| 3767 if (result.is_null()) return Failure::Exception(); | 3847 if (result.is_null()) return Failure::Exception(); |
| 3768 return *value; | 3848 return *value; |
| 3769 } | 3849 } |
| 3770 | 3850 |
| 3771 // Call-back into JavaScript to convert the key to a string. | 3851 // Call-back into JavaScript to convert the key to a string. |
| 3772 bool has_pending_exception = false; | 3852 bool has_pending_exception = false; |
| 3773 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); | 3853 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); |
| 3774 if (has_pending_exception) return Failure::Exception(); | 3854 if (has_pending_exception) return Failure::Exception(); |
| 3775 Handle<String> name = Handle<String>::cast(converted); | 3855 Handle<String> name = Handle<String>::cast(converted); |
| 3776 | 3856 |
| 3777 if (name->AsArrayIndex(&index)) { | 3857 if (name->AsArrayIndex(&index)) { |
| 3778 return js_object->SetElement(index, *value); | 3858 return js_object->SetElement(index, *value, strict_mode); |
| 3779 } else { | 3859 } else { |
| 3780 return js_object->SetProperty(*name, *value, attr); | 3860 return js_object->SetProperty(*name, *value, attr, strict_mode); |
| 3781 } | 3861 } |
| 3782 } | 3862 } |
| 3783 | 3863 |
| 3784 | 3864 |
| 3785 MaybeObject* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object, | 3865 MaybeObject* Runtime::ForceSetObjectProperty(Handle<JSObject> js_object, |
| 3786 Handle<Object> key, | 3866 Handle<Object> key, |
| 3787 Handle<Object> value, | 3867 Handle<Object> value, |
| 3788 PropertyAttributes attr) { | 3868 PropertyAttributes attr) { |
| 3789 HandleScope scope; | 3869 HandleScope scope; |
| 3790 | 3870 |
| 3791 // Check if the given key is an array index. | 3871 // Check if the given key is an array index. |
| 3792 uint32_t index; | 3872 uint32_t index; |
| 3793 if (key->ToArrayIndex(&index)) { | 3873 if (key->ToArrayIndex(&index)) { |
| 3794 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters | 3874 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters |
| 3795 // of a string using [] notation. We need to support this too in | 3875 // of a string using [] notation. We need to support this too in |
| 3796 // JavaScript. | 3876 // JavaScript. |
| 3797 // In the case of a String object we just need to redirect the assignment to | 3877 // In the case of a String object we just need to redirect the assignment to |
| 3798 // the underlying string if the index is in range. Since the underlying | 3878 // the underlying string if the index is in range. Since the underlying |
| 3799 // string does nothing with the assignment then we can ignore such | 3879 // string does nothing with the assignment then we can ignore such |
| 3800 // assignments. | 3880 // assignments. |
| 3801 if (js_object->IsStringObjectWithCharacterAt(index)) { | 3881 if (js_object->IsStringObjectWithCharacterAt(index)) { |
| 3802 return *value; | 3882 return *value; |
| 3803 } | 3883 } |
| 3804 | 3884 |
| 3805 return js_object->SetElement(index, *value); | 3885 return js_object->SetElement(index, *value, kNonStrictMode); |
| 3806 } | 3886 } |
| 3807 | 3887 |
| 3808 if (key->IsString()) { | 3888 if (key->IsString()) { |
| 3809 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { | 3889 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { |
| 3810 return js_object->SetElement(index, *value); | 3890 return js_object->SetElement(index, *value, kNonStrictMode); |
| 3811 } else { | 3891 } else { |
| 3812 Handle<String> key_string = Handle<String>::cast(key); | 3892 Handle<String> key_string = Handle<String>::cast(key); |
| 3813 key_string->TryFlatten(); | 3893 key_string->TryFlatten(); |
| 3814 return js_object->SetLocalPropertyIgnoreAttributes(*key_string, | 3894 return js_object->SetLocalPropertyIgnoreAttributes(*key_string, |
| 3815 *value, | 3895 *value, |
| 3816 attr); | 3896 attr); |
| 3817 } | 3897 } |
| 3818 } | 3898 } |
| 3819 | 3899 |
| 3820 // Call-back into JavaScript to convert the key to a string. | 3900 // Call-back into JavaScript to convert the key to a string. |
| 3821 bool has_pending_exception = false; | 3901 bool has_pending_exception = false; |
| 3822 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); | 3902 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); |
| 3823 if (has_pending_exception) return Failure::Exception(); | 3903 if (has_pending_exception) return Failure::Exception(); |
| 3824 Handle<String> name = Handle<String>::cast(converted); | 3904 Handle<String> name = Handle<String>::cast(converted); |
| 3825 | 3905 |
| 3826 if (name->AsArrayIndex(&index)) { | 3906 if (name->AsArrayIndex(&index)) { |
| 3827 return js_object->SetElement(index, *value); | 3907 return js_object->SetElement(index, *value, kNonStrictMode); |
| 3828 } else { | 3908 } else { |
| 3829 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); | 3909 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); |
| 3830 } | 3910 } |
| 3831 } | 3911 } |
| 3832 | 3912 |
| 3833 | 3913 |
| 3834 MaybeObject* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, | 3914 MaybeObject* Runtime::ForceDeleteObjectProperty(Handle<JSObject> js_object, |
| 3835 Handle<Object> key) { | 3915 Handle<Object> key) { |
| 3836 HandleScope scope; | 3916 HandleScope scope; |
| 3837 | 3917 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 3862 key_string = Handle<String>::cast(converted); | 3942 key_string = Handle<String>::cast(converted); |
| 3863 } | 3943 } |
| 3864 | 3944 |
| 3865 key_string->TryFlatten(); | 3945 key_string->TryFlatten(); |
| 3866 return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION); | 3946 return js_object->DeleteProperty(*key_string, JSObject::FORCE_DELETION); |
| 3867 } | 3947 } |
| 3868 | 3948 |
| 3869 | 3949 |
| 3870 static MaybeObject* Runtime_SetProperty(Arguments args) { | 3950 static MaybeObject* Runtime_SetProperty(Arguments args) { |
| 3871 NoHandleAllocation ha; | 3951 NoHandleAllocation ha; |
| 3872 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); | 3952 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5); |
| 3873 | 3953 |
| 3874 Handle<Object> object = args.at<Object>(0); | 3954 Handle<Object> object = args.at<Object>(0); |
| 3875 Handle<Object> key = args.at<Object>(1); | 3955 Handle<Object> key = args.at<Object>(1); |
| 3876 Handle<Object> value = args.at<Object>(2); | 3956 Handle<Object> value = args.at<Object>(2); |
| 3957 CONVERT_SMI_CHECKED(unchecked_attributes, args[3]); |
| 3958 RUNTIME_ASSERT( |
| 3959 (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); |
| 3960 // Compute attributes. |
| 3961 PropertyAttributes attributes = |
| 3962 static_cast<PropertyAttributes>(unchecked_attributes); |
| 3877 | 3963 |
| 3878 // Compute attributes. | 3964 StrictModeFlag strict_mode = kNonStrictMode; |
| 3879 PropertyAttributes attributes = NONE; | 3965 if (args.length() == 5) { |
| 3880 if (args.length() == 4) { | 3966 CONVERT_SMI_CHECKED(strict_unchecked, args[4]); |
| 3881 CONVERT_CHECKED(Smi, value_obj, args[3]); | 3967 RUNTIME_ASSERT(strict_unchecked == kStrictMode || |
| 3882 int unchecked_value = value_obj->value(); | 3968 strict_unchecked == kNonStrictMode); |
| 3883 // Only attribute bits should be set. | 3969 strict_mode = static_cast<StrictModeFlag>(strict_unchecked); |
| 3884 RUNTIME_ASSERT( | |
| 3885 (unchecked_value & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); | |
| 3886 attributes = static_cast<PropertyAttributes>(unchecked_value); | |
| 3887 } | 3970 } |
| 3888 return Runtime::SetObjectProperty(object, key, value, attributes); | 3971 |
| 3972 return Runtime::SetObjectProperty(object, |
| 3973 key, |
| 3974 value, |
| 3975 attributes, |
| 3976 strict_mode); |
| 3889 } | 3977 } |
| 3890 | 3978 |
| 3891 | 3979 |
| 3892 // Set a local property, even if it is READ_ONLY. If the property does not | 3980 // Set a local property, even if it is READ_ONLY. If the property does not |
| 3893 // exist, it will be added with attributes NONE. | 3981 // exist, it will be added with attributes NONE. |
| 3894 static MaybeObject* Runtime_IgnoreAttributesAndSetProperty(Arguments args) { | 3982 static MaybeObject* Runtime_IgnoreAttributesAndSetProperty(Arguments args) { |
| 3895 NoHandleAllocation ha; | 3983 NoHandleAllocation ha; |
| 3896 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); | 3984 RUNTIME_ASSERT(args.length() == 3 || args.length() == 4); |
| 3897 CONVERT_CHECKED(JSObject, object, args[0]); | 3985 CONVERT_CHECKED(JSObject, object, args[0]); |
| 3898 CONVERT_CHECKED(String, name, args[1]); | 3986 CONVERT_CHECKED(String, name, args[1]); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 3912 } | 4000 } |
| 3913 | 4001 |
| 3914 | 4002 |
| 3915 static MaybeObject* Runtime_DeleteProperty(Arguments args) { | 4003 static MaybeObject* Runtime_DeleteProperty(Arguments args) { |
| 3916 NoHandleAllocation ha; | 4004 NoHandleAllocation ha; |
| 3917 ASSERT(args.length() == 3); | 4005 ASSERT(args.length() == 3); |
| 3918 | 4006 |
| 3919 CONVERT_CHECKED(JSObject, object, args[0]); | 4007 CONVERT_CHECKED(JSObject, object, args[0]); |
| 3920 CONVERT_CHECKED(String, key, args[1]); | 4008 CONVERT_CHECKED(String, key, args[1]); |
| 3921 CONVERT_SMI_CHECKED(strict, args[2]); | 4009 CONVERT_SMI_CHECKED(strict, args[2]); |
| 3922 return object->DeleteProperty(key, strict == kStrictMode | 4010 return object->DeleteProperty(key, (strict == kStrictMode) |
| 3923 ? JSObject::STRICT_DELETION | 4011 ? JSObject::STRICT_DELETION |
| 3924 : JSObject::NORMAL_DELETION); | 4012 : JSObject::NORMAL_DELETION); |
| 3925 } | 4013 } |
| 3926 | 4014 |
| 3927 | 4015 |
| 3928 static Object* HasLocalPropertyImplementation(Handle<JSObject> object, | 4016 static Object* HasLocalPropertyImplementation(Handle<JSObject> object, |
| 3929 Handle<String> key) { | 4017 Handle<String> key) { |
| 3930 if (object->HasLocalProperty(*key)) return Heap::true_value(); | 4018 if (object->HasLocalProperty(*key)) return Heap::true_value(); |
| 3931 // Handle hidden prototypes. If there's a hidden prototype above this thing | 4019 // Handle hidden prototypes. If there's a hidden prototype above this thing |
| 3932 // then we have to check it for properties, because they are supposed to | 4020 // then we have to check it for properties, because they are supposed to |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4257 static MaybeObject* Runtime_GetArgumentsProperty(Arguments args) { | 4345 static MaybeObject* Runtime_GetArgumentsProperty(Arguments args) { |
| 4258 NoHandleAllocation ha; | 4346 NoHandleAllocation ha; |
| 4259 ASSERT(args.length() == 1); | 4347 ASSERT(args.length() == 1); |
| 4260 | 4348 |
| 4261 // Compute the frame holding the arguments. | 4349 // Compute the frame holding the arguments. |
| 4262 JavaScriptFrameIterator it; | 4350 JavaScriptFrameIterator it; |
| 4263 it.AdvanceToArgumentsFrame(); | 4351 it.AdvanceToArgumentsFrame(); |
| 4264 JavaScriptFrame* frame = it.frame(); | 4352 JavaScriptFrame* frame = it.frame(); |
| 4265 | 4353 |
| 4266 // Get the actual number of provided arguments. | 4354 // Get the actual number of provided arguments. |
| 4267 const uint32_t n = frame->GetProvidedParametersCount(); | 4355 const uint32_t n = frame->ComputeParametersCount(); |
| 4268 | 4356 |
| 4269 // Try to convert the key to an index. If successful and within | 4357 // Try to convert the key to an index. If successful and within |
| 4270 // index return the the argument from the frame. | 4358 // index return the the argument from the frame. |
| 4271 uint32_t index; | 4359 uint32_t index; |
| 4272 if (args[0]->ToArrayIndex(&index) && index < n) { | 4360 if (args[0]->ToArrayIndex(&index) && index < n) { |
| 4273 return frame->GetParameter(index); | 4361 return frame->GetParameter(index); |
| 4274 } | 4362 } |
| 4275 | 4363 |
| 4276 // Convert the key to a string. | 4364 // Convert the key to a string. |
| 4277 HandleScope scope; | 4365 HandleScope scope; |
| (...skipping 2540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6818 bound_args = FixedArray::cast(params->elements()); | 6906 bound_args = FixedArray::cast(params->elements()); |
| 6819 bound_argc = Smi::cast(params->length())->value(); | 6907 bound_argc = Smi::cast(params->length())->value(); |
| 6820 } | 6908 } |
| 6821 | 6909 |
| 6822 // Find frame containing arguments passed to the caller. | 6910 // Find frame containing arguments passed to the caller. |
| 6823 JavaScriptFrameIterator it; | 6911 JavaScriptFrameIterator it; |
| 6824 JavaScriptFrame* frame = it.frame(); | 6912 JavaScriptFrame* frame = it.frame(); |
| 6825 ASSERT(!frame->is_optimized()); | 6913 ASSERT(!frame->is_optimized()); |
| 6826 it.AdvanceToArgumentsFrame(); | 6914 it.AdvanceToArgumentsFrame(); |
| 6827 frame = it.frame(); | 6915 frame = it.frame(); |
| 6828 int argc = frame->GetProvidedParametersCount(); | 6916 int argc = frame->ComputeParametersCount(); |
| 6829 | 6917 |
| 6830 // Prepend bound arguments to caller's arguments. | 6918 // Prepend bound arguments to caller's arguments. |
| 6831 int total_argc = bound_argc + argc; | 6919 int total_argc = bound_argc + argc; |
| 6832 SmartPointer<Object**> param_data(NewArray<Object**>(total_argc)); | 6920 SmartPointer<Object**> param_data(NewArray<Object**>(total_argc)); |
| 6833 for (int i = 0; i < bound_argc; i++) { | 6921 for (int i = 0; i < bound_argc; i++) { |
| 6834 Handle<Object> val = Handle<Object>(bound_args->get(i)); | 6922 Handle<Object> val = Handle<Object>(bound_args->get(i)); |
| 6835 param_data[i] = val.location(); | 6923 param_data[i] = val.location(); |
| 6836 } | 6924 } |
| 6837 for (int i = 0; i < argc; i++) { | 6925 for (int i = 0; i < argc; i++) { |
| 6838 Handle<Object> val = Handle<Object>(frame->GetParameter(i)); | 6926 Handle<Object> val = Handle<Object>(frame->GetParameter(i)); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6926 if (!function->has_initial_map() && | 7014 if (!function->has_initial_map() && |
| 6927 shared->IsInobjectSlackTrackingInProgress()) { | 7015 shared->IsInobjectSlackTrackingInProgress()) { |
| 6928 // The tracking is already in progress for another function. We can only | 7016 // The tracking is already in progress for another function. We can only |
| 6929 // track one initial_map at a time, so we force the completion before the | 7017 // track one initial_map at a time, so we force the completion before the |
| 6930 // function is called as a constructor for the first time. | 7018 // function is called as a constructor for the first time. |
| 6931 shared->CompleteInobjectSlackTracking(); | 7019 shared->CompleteInobjectSlackTracking(); |
| 6932 } | 7020 } |
| 6933 | 7021 |
| 6934 bool first_allocation = !shared->live_objects_may_exist(); | 7022 bool first_allocation = !shared->live_objects_may_exist(); |
| 6935 Handle<JSObject> result = Factory::NewJSObject(function); | 7023 Handle<JSObject> result = Factory::NewJSObject(function); |
| 7024 RETURN_IF_EMPTY_HANDLE(result); |
| 6936 // Delay setting the stub if inobject slack tracking is in progress. | 7025 // Delay setting the stub if inobject slack tracking is in progress. |
| 6937 if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) { | 7026 if (first_allocation && !shared->IsInobjectSlackTrackingInProgress()) { |
| 6938 TrySettingInlineConstructStub(function); | 7027 TrySettingInlineConstructStub(function); |
| 6939 } | 7028 } |
| 6940 | 7029 |
| 6941 Counters::constructed_objects.Increment(); | 7030 Counters::constructed_objects.Increment(); |
| 6942 Counters::constructed_objects_runtime.Increment(); | 7031 Counters::constructed_objects_runtime.Increment(); |
| 6943 | 7032 |
| 6944 return *result; | 7033 return *result; |
| 6945 } | 7034 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6999 if (FLAG_trace_opt) { | 7088 if (FLAG_trace_opt) { |
| 7000 PrintF("[failed to optimize "); | 7089 PrintF("[failed to optimize "); |
| 7001 function->PrintName(); | 7090 function->PrintName(); |
| 7002 PrintF(": is code optimizable: %s, is debugger enabled: %s]\n", | 7091 PrintF(": is code optimizable: %s, is debugger enabled: %s]\n", |
| 7003 function->shared()->code()->optimizable() ? "T" : "F", | 7092 function->shared()->code()->optimizable() ? "T" : "F", |
| 7004 Debug::has_break_points() ? "T" : "F"); | 7093 Debug::has_break_points() ? "T" : "F"); |
| 7005 } | 7094 } |
| 7006 function->ReplaceCode(function->shared()->code()); | 7095 function->ReplaceCode(function->shared()->code()); |
| 7007 return function->code(); | 7096 return function->code(); |
| 7008 } | 7097 } |
| 7009 if (CompileOptimized(function, AstNode::kNoNumber)) { | 7098 if (CompileOptimized(function, AstNode::kNoNumber, CLEAR_EXCEPTION)) { |
| 7010 return function->code(); | 7099 return function->code(); |
| 7011 } | 7100 } |
| 7012 if (FLAG_trace_opt) { | 7101 if (FLAG_trace_opt) { |
| 7013 PrintF("[failed to optimize "); | 7102 PrintF("[failed to optimize "); |
| 7014 function->PrintName(); | 7103 function->PrintName(); |
| 7015 PrintF(": optimized compilation failed]\n"); | 7104 PrintF(": optimized compilation failed]\n"); |
| 7016 } | 7105 } |
| 7017 function->ReplaceCode(function->shared()->code()); | 7106 function->ReplaceCode(function->shared()->code()); |
| 7018 return Failure::Exception(); | 7107 return function->code(); |
| 7019 } | 7108 } |
| 7020 | 7109 |
| 7021 | 7110 |
| 7022 static MaybeObject* Runtime_NotifyDeoptimized(Arguments args) { | 7111 static MaybeObject* Runtime_NotifyDeoptimized(Arguments args) { |
| 7023 HandleScope scope; | 7112 HandleScope scope; |
| 7024 ASSERT(args.length() == 1); | 7113 ASSERT(args.length() == 1); |
| 7025 RUNTIME_ASSERT(args[0]->IsSmi()); | 7114 RUNTIME_ASSERT(args[0]->IsSmi()); |
| 7026 Deoptimizer::BailoutType type = | 7115 Deoptimizer::BailoutType type = |
| 7027 static_cast<Deoptimizer::BailoutType>(Smi::cast(args[0])->value()); | 7116 static_cast<Deoptimizer::BailoutType>(Smi::cast(args[0])->value()); |
| 7028 Deoptimizer* deoptimizer = Deoptimizer::Grab(); | 7117 Deoptimizer* deoptimizer = Deoptimizer::Grab(); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7168 ASSERT(ast_id != AstNode::kNoNumber); | 7257 ASSERT(ast_id != AstNode::kNoNumber); |
| 7169 if (FLAG_trace_osr) { | 7258 if (FLAG_trace_osr) { |
| 7170 PrintF("[replacing on-stack at AST id %d in ", ast_id); | 7259 PrintF("[replacing on-stack at AST id %d in ", ast_id); |
| 7171 function->PrintName(); | 7260 function->PrintName(); |
| 7172 PrintF("]\n"); | 7261 PrintF("]\n"); |
| 7173 } | 7262 } |
| 7174 | 7263 |
| 7175 // Try to compile the optimized code. A true return value from | 7264 // Try to compile the optimized code. A true return value from |
| 7176 // CompileOptimized means that compilation succeeded, not necessarily | 7265 // CompileOptimized means that compilation succeeded, not necessarily |
| 7177 // that optimization succeeded. | 7266 // that optimization succeeded. |
| 7178 if (CompileOptimized(function, ast_id) && function->IsOptimized()) { | 7267 if (CompileOptimized(function, ast_id, CLEAR_EXCEPTION) && |
| 7268 function->IsOptimized()) { |
| 7179 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 7269 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
| 7180 function->code()->deoptimization_data()); | 7270 function->code()->deoptimization_data()); |
| 7181 if (data->OsrPcOffset()->value() >= 0) { | 7271 if (data->OsrPcOffset()->value() >= 0) { |
| 7182 if (FLAG_trace_osr) { | 7272 if (FLAG_trace_osr) { |
| 7183 PrintF("[on-stack replacement offset %d in optimized code]\n", | 7273 PrintF("[on-stack replacement offset %d in optimized code]\n", |
| 7184 data->OsrPcOffset()->value()); | 7274 data->OsrPcOffset()->value()); |
| 7185 } | 7275 } |
| 7186 ASSERT(data->OsrAstId()->value() == ast_id); | 7276 ASSERT(data->OsrAstId()->value() == ast_id); |
| 7187 } else { | 7277 } else { |
| 7188 // We may never generate the desired OSR entry if we emit an | 7278 // We may never generate the desired OSR entry if we emit an |
| (...skipping 22 matching lines...) Expand all Loading... |
| 7211 // Allow OSR only at nesting level zero again. | 7301 // Allow OSR only at nesting level zero again. |
| 7212 unoptimized->set_allow_osr_at_loop_nesting_level(0); | 7302 unoptimized->set_allow_osr_at_loop_nesting_level(0); |
| 7213 | 7303 |
| 7214 // If the optimization attempt succeeded, return the AST id tagged as a | 7304 // If the optimization attempt succeeded, return the AST id tagged as a |
| 7215 // smi. This tells the builtin that we need to translate the unoptimized | 7305 // smi. This tells the builtin that we need to translate the unoptimized |
| 7216 // frame to an optimized one. | 7306 // frame to an optimized one. |
| 7217 if (succeeded) { | 7307 if (succeeded) { |
| 7218 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); | 7308 ASSERT(function->code()->kind() == Code::OPTIMIZED_FUNCTION); |
| 7219 return Smi::FromInt(ast_id); | 7309 return Smi::FromInt(ast_id); |
| 7220 } else { | 7310 } else { |
| 7311 if (function->IsMarkedForLazyRecompilation()) { |
| 7312 function->ReplaceCode(function->shared()->code()); |
| 7313 } |
| 7221 return Smi::FromInt(-1); | 7314 return Smi::FromInt(-1); |
| 7222 } | 7315 } |
| 7223 } | 7316 } |
| 7224 | 7317 |
| 7225 | 7318 |
| 7226 static MaybeObject* Runtime_GetFunctionDelegate(Arguments args) { | 7319 static MaybeObject* Runtime_GetFunctionDelegate(Arguments args) { |
| 7227 HandleScope scope; | 7320 HandleScope scope; |
| 7228 ASSERT(args.length() == 1); | 7321 ASSERT(args.length() == 1); |
| 7229 RUNTIME_ASSERT(!args[0]->IsJSFunction()); | 7322 RUNTIME_ASSERT(!args[0]->IsJSFunction()); |
| 7230 return *Execution::GetFunctionDelegate(args.at<Object>(0)); | 7323 return *Execution::GetFunctionDelegate(args.at<Object>(0)); |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7461 } | 7554 } |
| 7462 | 7555 |
| 7463 | 7556 |
| 7464 static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) { | 7557 static ObjectPair Runtime_LoadContextSlotNoReferenceError(Arguments args) { |
| 7465 return LoadContextSlotHelper(args, false); | 7558 return LoadContextSlotHelper(args, false); |
| 7466 } | 7559 } |
| 7467 | 7560 |
| 7468 | 7561 |
| 7469 static MaybeObject* Runtime_StoreContextSlot(Arguments args) { | 7562 static MaybeObject* Runtime_StoreContextSlot(Arguments args) { |
| 7470 HandleScope scope; | 7563 HandleScope scope; |
| 7471 ASSERT(args.length() == 3); | 7564 ASSERT(args.length() == 4); |
| 7472 | 7565 |
| 7473 Handle<Object> value(args[0]); | 7566 Handle<Object> value(args[0]); |
| 7474 CONVERT_ARG_CHECKED(Context, context, 1); | 7567 CONVERT_ARG_CHECKED(Context, context, 1); |
| 7475 CONVERT_ARG_CHECKED(String, name, 2); | 7568 CONVERT_ARG_CHECKED(String, name, 2); |
| 7569 CONVERT_SMI_CHECKED(strict_unchecked, args[3]); |
| 7570 RUNTIME_ASSERT(strict_unchecked == kStrictMode || |
| 7571 strict_unchecked == kNonStrictMode); |
| 7572 StrictModeFlag strict_mode = static_cast<StrictModeFlag>(strict_unchecked); |
| 7476 | 7573 |
| 7477 int index; | 7574 int index; |
| 7478 PropertyAttributes attributes; | 7575 PropertyAttributes attributes; |
| 7479 ContextLookupFlags flags = FOLLOW_CHAINS; | 7576 ContextLookupFlags flags = FOLLOW_CHAINS; |
| 7480 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); | 7577 Handle<Object> holder = context->Lookup(name, flags, &index, &attributes); |
| 7481 | 7578 |
| 7482 if (index >= 0) { | 7579 if (index >= 0) { |
| 7483 if (holder->IsContext()) { | 7580 if (holder->IsContext()) { |
| 7484 // Ignore if read_only variable. | 7581 // Ignore if read_only variable. |
| 7485 if ((attributes & READ_ONLY) == 0) { | 7582 if ((attributes & READ_ONLY) == 0) { |
| 7486 // Context is a fixed array and set cannot fail. | 7583 // Context is a fixed array and set cannot fail. |
| 7487 Context::cast(*holder)->set(index, *value); | 7584 Context::cast(*holder)->set(index, *value); |
| 7585 } else if (strict_mode == kStrictMode) { |
| 7586 // Setting read only property in strict mode. |
| 7587 Handle<Object> error = |
| 7588 Factory::NewTypeError("strict_cannot_assign", |
| 7589 HandleVector(&name, 1)); |
| 7590 return Top::Throw(*error); |
| 7488 } | 7591 } |
| 7489 } else { | 7592 } else { |
| 7490 ASSERT((attributes & READ_ONLY) == 0); | 7593 ASSERT((attributes & READ_ONLY) == 0); |
| 7491 Handle<Object> result = | 7594 Handle<Object> result = |
| 7492 SetElement(Handle<JSObject>::cast(holder), index, value); | 7595 SetElement(Handle<JSObject>::cast(holder), index, value, strict_mode); |
| 7493 if (result.is_null()) { | 7596 if (result.is_null()) { |
| 7494 ASSERT(Top::has_pending_exception()); | 7597 ASSERT(Top::has_pending_exception()); |
| 7495 return Failure::Exception(); | 7598 return Failure::Exception(); |
| 7496 } | 7599 } |
| 7497 } | 7600 } |
| 7498 return *value; | 7601 return *value; |
| 7499 } | 7602 } |
| 7500 | 7603 |
| 7501 // Slow case: The property is not in a FixedArray context. | 7604 // Slow case: The property is not in a FixedArray context. |
| 7502 // It is either in an JSObject extension context or it was not found. | 7605 // It is either in an JSObject extension context or it was not found. |
| 7503 Handle<JSObject> context_ext; | 7606 Handle<JSObject> context_ext; |
| 7504 | 7607 |
| 7505 if (!holder.is_null()) { | 7608 if (!holder.is_null()) { |
| 7506 // The property exists in the extension context. | 7609 // The property exists in the extension context. |
| 7507 context_ext = Handle<JSObject>::cast(holder); | 7610 context_ext = Handle<JSObject>::cast(holder); |
| 7508 } else { | 7611 } else { |
| 7509 // The property was not found. It needs to be stored in the global context. | 7612 // The property was not found. It needs to be stored in the global context. |
| 7510 ASSERT(attributes == ABSENT); | 7613 ASSERT(attributes == ABSENT); |
| 7511 attributes = NONE; | 7614 attributes = NONE; |
| 7512 context_ext = Handle<JSObject>(Top::context()->global()); | 7615 context_ext = Handle<JSObject>(Top::context()->global()); |
| 7513 } | 7616 } |
| 7514 | 7617 |
| 7515 // Set the property, but ignore if read_only variable on the context | 7618 // Set the property, but ignore if read_only variable on the context |
| 7516 // extension object itself. | 7619 // extension object itself. |
| 7517 if ((attributes & READ_ONLY) == 0 || | 7620 if ((attributes & READ_ONLY) == 0 || |
| 7518 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { | 7621 (context_ext->GetLocalPropertyAttribute(*name) == ABSENT)) { |
| 7519 RETURN_IF_EMPTY_HANDLE(SetProperty(context_ext, name, value, NONE)); | 7622 RETURN_IF_EMPTY_HANDLE( |
| 7623 SetProperty(context_ext, name, value, NONE, strict_mode)); |
| 7624 } else if (strict_mode == kStrictMode && (attributes & READ_ONLY) != 0) { |
| 7625 // Setting read only property in strict mode. |
| 7626 Handle<Object> error = |
| 7627 Factory::NewTypeError("strict_cannot_assign", HandleVector(&name, 1)); |
| 7628 return Top::Throw(*error); |
| 7520 } | 7629 } |
| 7521 return *value; | 7630 return *value; |
| 7522 } | 7631 } |
| 7523 | 7632 |
| 7524 | 7633 |
| 7525 static MaybeObject* Runtime_Throw(Arguments args) { | 7634 static MaybeObject* Runtime_Throw(Arguments args) { |
| 7526 HandleScope scope; | 7635 HandleScope scope; |
| 7527 ASSERT(args.length() == 1); | 7636 ASSERT(args.length() == 1); |
| 7528 | 7637 |
| 7529 return Top::Throw(args[0]); | 7638 return Top::Throw(args[0]); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7636 if (fun->IsJSFunction()) { | 7745 if (fun->IsJSFunction()) { |
| 7637 PrintObject(JSFunction::cast(fun)->shared()->name()); | 7746 PrintObject(JSFunction::cast(fun)->shared()->name()); |
| 7638 } else { | 7747 } else { |
| 7639 PrintObject(fun); | 7748 PrintObject(fun); |
| 7640 } | 7749 } |
| 7641 // function arguments | 7750 // function arguments |
| 7642 // (we are intentionally only printing the actually | 7751 // (we are intentionally only printing the actually |
| 7643 // supplied parameters, not all parameters required) | 7752 // supplied parameters, not all parameters required) |
| 7644 PrintF("(this="); | 7753 PrintF("(this="); |
| 7645 PrintObject(frame->receiver()); | 7754 PrintObject(frame->receiver()); |
| 7646 const int length = frame->GetProvidedParametersCount(); | 7755 const int length = frame->ComputeParametersCount(); |
| 7647 for (int i = 0; i < length; i++) { | 7756 for (int i = 0; i < length; i++) { |
| 7648 PrintF(", "); | 7757 PrintF(", "); |
| 7649 PrintObject(frame->GetParameter(i)); | 7758 PrintObject(frame->GetParameter(i)); |
| 7650 } | 7759 } |
| 7651 PrintF(") {\n"); | 7760 PrintF(") {\n"); |
| 7652 | 7761 |
| 7653 } else { | 7762 } else { |
| 7654 // function result | 7763 // function result |
| 7655 PrintF("} -> "); | 7764 PrintF("} -> "); |
| 7656 PrintObject(result); | 7765 PrintObject(result); |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7819 kNonStrictMode); | 7928 kNonStrictMode); |
| 7820 if (shared.is_null()) return Failure::Exception(); | 7929 if (shared.is_null()) return Failure::Exception(); |
| 7821 Handle<JSFunction> fun = | 7930 Handle<JSFunction> fun = |
| 7822 Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED); | 7931 Factory::NewFunctionFromSharedFunctionInfo(shared, context, NOT_TENURED); |
| 7823 return *fun; | 7932 return *fun; |
| 7824 } | 7933 } |
| 7825 | 7934 |
| 7826 | 7935 |
| 7827 static ObjectPair CompileGlobalEval(Handle<String> source, | 7936 static ObjectPair CompileGlobalEval(Handle<String> source, |
| 7828 Handle<Object> receiver, | 7937 Handle<Object> receiver, |
| 7829 StrictModeFlag mode) { | 7938 StrictModeFlag strict_mode) { |
| 7830 // Deal with a normal eval call with a string argument. Compile it | 7939 // Deal with a normal eval call with a string argument. Compile it |
| 7831 // and return the compiled function bound in the local context. | 7940 // and return the compiled function bound in the local context. |
| 7832 Handle<SharedFunctionInfo> shared = Compiler::CompileEval( | 7941 Handle<SharedFunctionInfo> shared = Compiler::CompileEval( |
| 7833 source, | 7942 source, |
| 7834 Handle<Context>(Top::context()), | 7943 Handle<Context>(Top::context()), |
| 7835 Top::context()->IsGlobalContext(), | 7944 Top::context()->IsGlobalContext(), |
| 7836 mode); | 7945 strict_mode); |
| 7837 if (shared.is_null()) return MakePair(Failure::Exception(), NULL); | 7946 if (shared.is_null()) return MakePair(Failure::Exception(), NULL); |
| 7838 Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo( | 7947 Handle<JSFunction> compiled = Factory::NewFunctionFromSharedFunctionInfo( |
| 7839 shared, | 7948 shared, |
| 7840 Handle<Context>(Top::context()), | 7949 Handle<Context>(Top::context()), |
| 7841 NOT_TENURED); | 7950 NOT_TENURED); |
| 7842 return MakePair(*compiled, *receiver); | 7951 return MakePair(*compiled, *receiver); |
| 7843 } | 7952 } |
| 7844 | 7953 |
| 7845 | 7954 |
| 7846 static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) { | 7955 static ObjectPair Runtime_ResolvePossiblyDirectEval(Arguments args) { |
| 7847 ASSERT(args.length() == 4); | 7956 ASSERT(args.length() == 4); |
| 7848 if (!args[0]->IsJSFunction()) { | |
| 7849 return MakePair(Top::ThrowIllegalOperation(), NULL); | |
| 7850 } | |
| 7851 | 7957 |
| 7852 HandleScope scope; | 7958 HandleScope scope; |
| 7853 Handle<JSFunction> callee = args.at<JSFunction>(0); | 7959 Handle<Object> callee = args.at<Object>(0); |
| 7854 Handle<Object> receiver; // Will be overwritten. | 7960 Handle<Object> receiver; // Will be overwritten. |
| 7855 | 7961 |
| 7856 // Compute the calling context. | 7962 // Compute the calling context. |
| 7857 Handle<Context> context = Handle<Context>(Top::context()); | 7963 Handle<Context> context = Handle<Context>(Top::context()); |
| 7858 #ifdef DEBUG | 7964 #ifdef DEBUG |
| 7859 // Make sure Top::context() agrees with the old code that traversed | 7965 // Make sure Top::context() agrees with the old code that traversed |
| 7860 // the stack frames to compute the context. | 7966 // the stack frames to compute the context. |
| 7861 StackFrameLocator locator; | 7967 StackFrameLocator locator; |
| 7862 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 7968 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| 7863 ASSERT(Context::cast(frame->context()) == *context); | 7969 ASSERT(Context::cast(frame->context()) == *context); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7911 ASSERT(args[3]->IsSmi()); | 8017 ASSERT(args[3]->IsSmi()); |
| 7912 return CompileGlobalEval(args.at<String>(1), | 8018 return CompileGlobalEval(args.at<String>(1), |
| 7913 args.at<Object>(2), | 8019 args.at<Object>(2), |
| 7914 static_cast<StrictModeFlag>( | 8020 static_cast<StrictModeFlag>( |
| 7915 Smi::cast(args[3])->value())); | 8021 Smi::cast(args[3])->value())); |
| 7916 } | 8022 } |
| 7917 | 8023 |
| 7918 | 8024 |
| 7919 static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments args) { | 8025 static ObjectPair Runtime_ResolvePossiblyDirectEvalNoLookup(Arguments args) { |
| 7920 ASSERT(args.length() == 4); | 8026 ASSERT(args.length() == 4); |
| 7921 if (!args[0]->IsJSFunction()) { | |
| 7922 return MakePair(Top::ThrowIllegalOperation(), NULL); | |
| 7923 } | |
| 7924 | 8027 |
| 7925 HandleScope scope; | 8028 HandleScope scope; |
| 7926 Handle<JSFunction> callee = args.at<JSFunction>(0); | 8029 Handle<Object> callee = args.at<Object>(0); |
| 7927 | 8030 |
| 7928 // 'eval' is bound in the global context, but it may have been overwritten. | 8031 // 'eval' is bound in the global context, but it may have been overwritten. |
| 7929 // Compare it to the builtin 'GlobalEval' function to make sure. | 8032 // Compare it to the builtin 'GlobalEval' function to make sure. |
| 7930 if (*callee != Top::global_context()->global_eval_fun() || | 8033 if (*callee != Top::global_context()->global_eval_fun() || |
| 7931 !args[1]->IsString()) { | 8034 !args[1]->IsString()) { |
| 7932 return MakePair(*callee, Top::context()->global()->global_receiver()); | 8035 return MakePair(*callee, Top::context()->global()->global_receiver()); |
| 7933 } | 8036 } |
| 7934 | 8037 |
| 7935 ASSERT(args[3]->IsSmi()); | 8038 ASSERT(args[3]->IsSmi()); |
| 7936 return CompileGlobalEval(args.at<String>(1), | 8039 return CompileGlobalEval(args.at<String>(1), |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7986 ASSERT(args.length() == 2); | 8089 ASSERT(args.length() == 2); |
| 7987 CONVERT_CHECKED(JSArray, array, args[0]); | 8090 CONVERT_CHECKED(JSArray, array, args[0]); |
| 7988 CONVERT_CHECKED(JSObject, element, args[1]); | 8091 CONVERT_CHECKED(JSObject, element, args[1]); |
| 7989 RUNTIME_ASSERT(array->HasFastElements()); | 8092 RUNTIME_ASSERT(array->HasFastElements()); |
| 7990 int length = Smi::cast(array->length())->value(); | 8093 int length = Smi::cast(array->length())->value(); |
| 7991 FixedArray* elements = FixedArray::cast(array->elements()); | 8094 FixedArray* elements = FixedArray::cast(array->elements()); |
| 7992 for (int i = 0; i < length; i++) { | 8095 for (int i = 0; i < length; i++) { |
| 7993 if (elements->get(i) == element) return Heap::false_value(); | 8096 if (elements->get(i) == element) return Heap::false_value(); |
| 7994 } | 8097 } |
| 7995 Object* obj; | 8098 Object* obj; |
| 7996 { MaybeObject* maybe_obj = array->SetFastElement(length, element); | 8099 // Strict not needed. Used for cycle detection in Array join implementation. |
| 8100 { MaybeObject* maybe_obj = array->SetFastElement(length, element, |
| 8101 kNonStrictMode); |
| 7997 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8102 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7998 } | 8103 } |
| 7999 return Heap::true_value(); | 8104 return Heap::true_value(); |
| 8000 } | 8105 } |
| 8001 | 8106 |
| 8002 | 8107 |
| 8003 /** | 8108 /** |
| 8004 * A simple visitor visits every element of Array's. | 8109 * A simple visitor visits every element of Array's. |
| 8005 * The backend storage can be a fixed array for fast elements case, | 8110 * The backend storage can be a fixed array for fast elements case, |
| 8006 * or a dictionary for sparse array. Since Dictionary is a subtype | 8111 * or a dictionary for sparse array. Since Dictionary is a subtype |
| 8007 * of FixedArray, the class can be used by both fast and slow cases. | 8112 * of FixedArray, the class can be used by both fast and slow cases. |
| 8008 * The second parameter of the constructor, fast_elements, specifies | 8113 * The second parameter of the constructor, fast_elements, specifies |
| 8009 * whether the storage is a FixedArray or Dictionary. | 8114 * whether the storage is a FixedArray or Dictionary. |
| 8010 * | 8115 * |
| 8011 * An index limit is used to deal with the situation that a result array | 8116 * An index limit is used to deal with the situation that a result array |
| 8012 * length overflows 32-bit non-negative integer. | 8117 * length overflows 32-bit non-negative integer. |
| 8013 */ | 8118 */ |
| 8014 class ArrayConcatVisitor { | 8119 class ArrayConcatVisitor { |
| 8015 public: | 8120 public: |
| 8016 ArrayConcatVisitor(Handle<FixedArray> storage, | 8121 ArrayConcatVisitor(Handle<FixedArray> storage, |
| 8017 uint32_t index_limit, | |
| 8018 bool fast_elements) : | 8122 bool fast_elements) : |
| 8019 storage_(storage), index_limit_(index_limit), | 8123 storage_(Handle<FixedArray>::cast(GlobalHandles::Create(*storage))), |
| 8020 index_offset_(0), fast_elements_(fast_elements) { } | 8124 index_offset_(0u), |
| 8125 fast_elements_(fast_elements) { } |
| 8126 |
| 8127 ~ArrayConcatVisitor() { |
| 8128 clear_storage(); |
| 8129 } |
| 8021 | 8130 |
| 8022 void visit(uint32_t i, Handle<Object> elm) { | 8131 void visit(uint32_t i, Handle<Object> elm) { |
| 8023 if (i >= index_limit_ - index_offset_) return; | 8132 if (i >= JSObject::kMaxElementCount - index_offset_) return; |
| 8024 uint32_t index = index_offset_ + i; | 8133 uint32_t index = index_offset_ + i; |
| 8025 | 8134 |
| 8026 if (fast_elements_) { | 8135 if (fast_elements_) { |
| 8027 ASSERT(index < static_cast<uint32_t>(storage_->length())); | 8136 if (index < static_cast<uint32_t>(storage_->length())) { |
| 8028 storage_->set(index, *elm); | 8137 storage_->set(index, *elm); |
| 8029 | 8138 return; |
| 8030 } else { | 8139 } |
| 8031 Handle<NumberDictionary> dict = Handle<NumberDictionary>::cast(storage_); | 8140 // Our initial estimate of length was foiled, possibly by |
| 8032 Handle<NumberDictionary> result = | 8141 // getters on the arrays increasing the length of later arrays |
| 8033 Factory::DictionaryAtNumberPut(dict, index, elm); | 8142 // during iteration. |
| 8034 if (!result.is_identical_to(dict)) | 8143 // This shouldn't happen in anything but pathological cases. |
| 8035 storage_ = result; | 8144 SetDictionaryMode(index); |
| 8036 } | 8145 // Fall-through to dictionary mode. |
| 8037 } | 8146 } |
| 8147 ASSERT(!fast_elements_); |
| 8148 Handle<NumberDictionary> dict(NumberDictionary::cast(*storage_)); |
| 8149 Handle<NumberDictionary> result = |
| 8150 Factory::DictionaryAtNumberPut(dict, index, elm); |
| 8151 if (!result.is_identical_to(dict)) { |
| 8152 // Dictionary needed to grow. |
| 8153 clear_storage(); |
| 8154 set_storage(*result); |
| 8155 } |
| 8156 } |
| 8038 | 8157 |
| 8039 void increase_index_offset(uint32_t delta) { | 8158 void increase_index_offset(uint32_t delta) { |
| 8040 if (index_limit_ - index_offset_ < delta) { | 8159 if (JSObject::kMaxElementCount - index_offset_ < delta) { |
| 8041 index_offset_ = index_limit_; | 8160 index_offset_ = JSObject::kMaxElementCount; |
| 8042 } else { | 8161 } else { |
| 8043 index_offset_ += delta; | 8162 index_offset_ += delta; |
| 8044 } | 8163 } |
| 8045 } | 8164 } |
| 8046 | 8165 |
| 8047 Handle<FixedArray> storage() { return storage_; } | 8166 Handle<JSArray> ToArray() { |
| 8167 Handle<JSArray> array = Factory::NewJSArray(0); |
| 8168 Handle<Object> length = |
| 8169 Factory::NewNumber(static_cast<double>(index_offset_)); |
| 8170 Handle<Map> map; |
| 8171 if (fast_elements_) { |
| 8172 map = Factory::GetFastElementsMap(Handle<Map>(array->map())); |
| 8173 } else { |
| 8174 map = Factory::GetSlowElementsMap(Handle<Map>(array->map())); |
| 8175 } |
| 8176 array->set_map(*map); |
| 8177 array->set_length(*length); |
| 8178 array->set_elements(*storage_); |
| 8179 return array; |
| 8180 } |
| 8048 | 8181 |
| 8049 private: | 8182 private: |
| 8050 Handle<FixedArray> storage_; | 8183 // Convert storage to dictionary mode. |
| 8051 // Limit on the accepted indices. Elements with indices larger than the | 8184 void SetDictionaryMode(uint32_t index) { |
| 8052 // limit are ignored by the visitor. | 8185 ASSERT(fast_elements_); |
| 8053 uint32_t index_limit_; | 8186 Handle<FixedArray> current_storage(*storage_); |
| 8054 // Index after last seen index. Always less than or equal to index_limit_. | 8187 Handle<NumberDictionary> slow_storage( |
| 8188 Factory::NewNumberDictionary(current_storage->length())); |
| 8189 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); |
| 8190 for (uint32_t i = 0; i < current_length; i++) { |
| 8191 HandleScope loop_scope; |
| 8192 Handle<Object> element(current_storage->get(i)); |
| 8193 if (!element->IsTheHole()) { |
| 8194 Handle<NumberDictionary> new_storage = |
| 8195 Factory::DictionaryAtNumberPut(slow_storage, i, element); |
| 8196 if (!new_storage.is_identical_to(slow_storage)) { |
| 8197 slow_storage = loop_scope.CloseAndEscape(new_storage); |
| 8198 } |
| 8199 } |
| 8200 } |
| 8201 clear_storage(); |
| 8202 set_storage(*slow_storage); |
| 8203 fast_elements_ = false; |
| 8204 } |
| 8205 |
| 8206 inline void clear_storage() { |
| 8207 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location()); |
| 8208 } |
| 8209 |
| 8210 inline void set_storage(FixedArray* storage) { |
| 8211 storage_ = Handle<FixedArray>::cast(GlobalHandles::Create(storage)); |
| 8212 } |
| 8213 |
| 8214 Handle<FixedArray> storage_; // Always a global handle. |
| 8215 // Index after last seen index. Always less than or equal to |
| 8216 // JSObject::kMaxElementCount. |
| 8055 uint32_t index_offset_; | 8217 uint32_t index_offset_; |
| 8056 const bool fast_elements_; | 8218 bool fast_elements_; |
| 8057 }; | 8219 }; |
| 8058 | 8220 |
| 8059 | 8221 |
| 8222 static uint32_t EstimateElementCount(Handle<JSArray> array) { |
| 8223 uint32_t length = static_cast<uint32_t>(array->length()->Number()); |
| 8224 int element_count = 0; |
| 8225 switch (array->GetElementsKind()) { |
| 8226 case JSObject::FAST_ELEMENTS: { |
| 8227 // Fast elements can't have lengths that are not representable by |
| 8228 // a 32-bit signed integer. |
| 8229 ASSERT(static_cast<int32_t>(FixedArray::kMaxLength) >= 0); |
| 8230 int fast_length = static_cast<int>(length); |
| 8231 Handle<FixedArray> elements(FixedArray::cast(array->elements())); |
| 8232 for (int i = 0; i < fast_length; i++) { |
| 8233 if (!elements->get(i)->IsTheHole()) element_count++; |
| 8234 } |
| 8235 break; |
| 8236 } |
| 8237 case JSObject::DICTIONARY_ELEMENTS: { |
| 8238 Handle<NumberDictionary> dictionary( |
| 8239 NumberDictionary::cast(array->elements())); |
| 8240 int capacity = dictionary->Capacity(); |
| 8241 for (int i = 0; i < capacity; i++) { |
| 8242 Handle<Object> key(dictionary->KeyAt(i)); |
| 8243 if (dictionary->IsKey(*key)) { |
| 8244 element_count++; |
| 8245 } |
| 8246 } |
| 8247 break; |
| 8248 } |
| 8249 default: |
| 8250 // External arrays are always dense. |
| 8251 return length; |
| 8252 } |
| 8253 // As an estimate, we assume that the prototype doesn't contain any |
| 8254 // inherited elements. |
| 8255 return element_count; |
| 8256 } |
| 8257 |
| 8258 |
| 8259 |
| 8060 template<class ExternalArrayClass, class ElementType> | 8260 template<class ExternalArrayClass, class ElementType> |
| 8061 static uint32_t IterateExternalArrayElements(Handle<JSObject> receiver, | 8261 static void IterateExternalArrayElements(Handle<JSObject> receiver, |
| 8062 bool elements_are_ints, | 8262 bool elements_are_ints, |
| 8063 bool elements_are_guaranteed_smis, | 8263 bool elements_are_guaranteed_smis, |
| 8064 uint32_t range, | 8264 ArrayConcatVisitor* visitor) { |
| 8065 ArrayConcatVisitor* visitor) { | |
| 8066 Handle<ExternalArrayClass> array( | 8265 Handle<ExternalArrayClass> array( |
| 8067 ExternalArrayClass::cast(receiver->elements())); | 8266 ExternalArrayClass::cast(receiver->elements())); |
| 8068 uint32_t len = Min(static_cast<uint32_t>(array->length()), range); | 8267 uint32_t len = static_cast<uint32_t>(array->length()); |
| 8069 | 8268 |
| 8070 if (visitor != NULL) { | 8269 ASSERT(visitor != NULL); |
| 8071 if (elements_are_ints) { | 8270 if (elements_are_ints) { |
| 8072 if (elements_are_guaranteed_smis) { | 8271 if (elements_are_guaranteed_smis) { |
| 8073 for (uint32_t j = 0; j < len; j++) { | 8272 for (uint32_t j = 0; j < len; j++) { |
| 8074 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j)))); | 8273 HandleScope loop_scope; |
| 8075 visitor->visit(j, e); | 8274 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get(j)))); |
| 8076 } | 8275 visitor->visit(j, e); |
| 8077 } else { | |
| 8078 for (uint32_t j = 0; j < len; j++) { | |
| 8079 int64_t val = static_cast<int64_t>(array->get(j)); | |
| 8080 if (Smi::IsValid(static_cast<intptr_t>(val))) { | |
| 8081 Handle<Smi> e(Smi::FromInt(static_cast<int>(val))); | |
| 8082 visitor->visit(j, e); | |
| 8083 } else { | |
| 8084 Handle<Object> e = | |
| 8085 Factory::NewNumber(static_cast<ElementType>(val)); | |
| 8086 visitor->visit(j, e); | |
| 8087 } | |
| 8088 } | |
| 8089 } | 8276 } |
| 8090 } else { | 8277 } else { |
| 8091 for (uint32_t j = 0; j < len; j++) { | 8278 for (uint32_t j = 0; j < len; j++) { |
| 8092 Handle<Object> e = Factory::NewNumber(array->get(j)); | 8279 HandleScope loop_scope; |
| 8093 visitor->visit(j, e); | 8280 int64_t val = static_cast<int64_t>(array->get(j)); |
| 8094 } | 8281 if (Smi::IsValid(static_cast<intptr_t>(val))) { |
| 8095 } | 8282 Handle<Smi> e(Smi::FromInt(static_cast<int>(val))); |
| 8096 } | 8283 visitor->visit(j, e); |
| 8097 | 8284 } else { |
| 8098 return len; | 8285 Handle<Object> e = |
| 8099 } | 8286 Factory::NewNumber(static_cast<ElementType>(val)); |
| 8100 | 8287 visitor->visit(j, e); |
| 8101 /** | 8288 } |
| 8102 * A helper function that visits elements of a JSObject. Only elements | 8289 } |
| 8103 * whose index between 0 and range (exclusive) are visited. | 8290 } |
| 8104 * | 8291 } else { |
| 8105 * If the third parameter, visitor, is not NULL, the visitor is called | 8292 for (uint32_t j = 0; j < len; j++) { |
| 8106 * with parameters, 'visitor_index_offset + element index' and the element. | 8293 HandleScope loop_scope; |
| 8107 * | 8294 Handle<Object> e = Factory::NewNumber(array->get(j)); |
| 8108 * It returns the number of visisted elements. | 8295 visitor->visit(j, e); |
| 8109 */ | 8296 } |
| 8110 static uint32_t IterateElements(Handle<JSObject> receiver, | 8297 } |
| 8111 uint32_t range, | 8298 } |
| 8112 ArrayConcatVisitor* visitor) { | 8299 |
| 8113 uint32_t num_of_elements = 0; | 8300 |
| 8114 | 8301 // Used for sorting indices in a List<uint32_t>. |
| 8115 switch (receiver->GetElementsKind()) { | 8302 static int compareUInt32(const uint32_t* ap, const uint32_t* bp) { |
| 8303 uint32_t a = *ap; |
| 8304 uint32_t b = *bp; |
| 8305 return (a == b) ? 0 : (a < b) ? -1 : 1; |
| 8306 } |
| 8307 |
| 8308 |
| 8309 static void CollectElementIndices(Handle<JSObject> object, |
| 8310 uint32_t range, |
| 8311 List<uint32_t>* indices) { |
| 8312 JSObject::ElementsKind kind = object->GetElementsKind(); |
| 8313 switch (kind) { |
| 8116 case JSObject::FAST_ELEMENTS: { | 8314 case JSObject::FAST_ELEMENTS: { |
| 8117 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); | 8315 Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
| 8118 uint32_t len = elements->length(); | 8316 uint32_t length = static_cast<uint32_t>(elements->length()); |
| 8119 if (range < len) { | 8317 if (range < length) length = range; |
| 8120 len = range; | 8318 for (uint32_t i = 0; i < length; i++) { |
| 8121 } | 8319 if (!elements->get(i)->IsTheHole()) { |
| 8122 | 8320 indices->Add(i); |
| 8123 for (uint32_t j = 0; j < len; j++) { | 8321 } |
| 8124 Handle<Object> e(elements->get(j)); | 8322 } |
| 8125 if (!e->IsTheHole()) { | |
| 8126 num_of_elements++; | |
| 8127 if (visitor) { | |
| 8128 visitor->visit(j, e); | |
| 8129 } | |
| 8130 } | |
| 8131 } | |
| 8132 break; | |
| 8133 } | |
| 8134 case JSObject::PIXEL_ELEMENTS: { | |
| 8135 Handle<PixelArray> pixels(PixelArray::cast(receiver->elements())); | |
| 8136 uint32_t len = pixels->length(); | |
| 8137 if (range < len) { | |
| 8138 len = range; | |
| 8139 } | |
| 8140 | |
| 8141 for (uint32_t j = 0; j < len; j++) { | |
| 8142 num_of_elements++; | |
| 8143 if (visitor != NULL) { | |
| 8144 Handle<Smi> e(Smi::FromInt(pixels->get(j))); | |
| 8145 visitor->visit(j, e); | |
| 8146 } | |
| 8147 } | |
| 8148 break; | |
| 8149 } | |
| 8150 case JSObject::EXTERNAL_BYTE_ELEMENTS: { | |
| 8151 num_of_elements = | |
| 8152 IterateExternalArrayElements<ExternalByteArray, int8_t>( | |
| 8153 receiver, true, true, range, visitor); | |
| 8154 break; | |
| 8155 } | |
| 8156 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | |
| 8157 num_of_elements = | |
| 8158 IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>( | |
| 8159 receiver, true, true, range, visitor); | |
| 8160 break; | |
| 8161 } | |
| 8162 case JSObject::EXTERNAL_SHORT_ELEMENTS: { | |
| 8163 num_of_elements = | |
| 8164 IterateExternalArrayElements<ExternalShortArray, int16_t>( | |
| 8165 receiver, true, true, range, visitor); | |
| 8166 break; | |
| 8167 } | |
| 8168 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { | |
| 8169 num_of_elements = | |
| 8170 IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>( | |
| 8171 receiver, true, true, range, visitor); | |
| 8172 break; | |
| 8173 } | |
| 8174 case JSObject::EXTERNAL_INT_ELEMENTS: { | |
| 8175 num_of_elements = | |
| 8176 IterateExternalArrayElements<ExternalIntArray, int32_t>( | |
| 8177 receiver, true, false, range, visitor); | |
| 8178 break; | |
| 8179 } | |
| 8180 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: { | |
| 8181 num_of_elements = | |
| 8182 IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>( | |
| 8183 receiver, true, false, range, visitor); | |
| 8184 break; | |
| 8185 } | |
| 8186 case JSObject::EXTERNAL_FLOAT_ELEMENTS: { | |
| 8187 num_of_elements = | |
| 8188 IterateExternalArrayElements<ExternalFloatArray, float>( | |
| 8189 receiver, false, false, range, visitor); | |
| 8190 break; | 8323 break; |
| 8191 } | 8324 } |
| 8192 case JSObject::DICTIONARY_ELEMENTS: { | 8325 case JSObject::DICTIONARY_ELEMENTS: { |
| 8193 Handle<NumberDictionary> dict(receiver->element_dictionary()); | 8326 Handle<NumberDictionary> dict(NumberDictionary::cast(object->elements())); |
| 8194 uint32_t capacity = dict->Capacity(); | 8327 uint32_t capacity = dict->Capacity(); |
| 8195 for (uint32_t j = 0; j < capacity; j++) { | 8328 for (uint32_t j = 0; j < capacity; j++) { |
| 8329 HandleScope loop_scope; |
| 8196 Handle<Object> k(dict->KeyAt(j)); | 8330 Handle<Object> k(dict->KeyAt(j)); |
| 8197 if (dict->IsKey(*k)) { | 8331 if (dict->IsKey(*k)) { |
| 8198 ASSERT(k->IsNumber()); | 8332 ASSERT(k->IsNumber()); |
| 8199 uint32_t index = static_cast<uint32_t>(k->Number()); | 8333 uint32_t index = static_cast<uint32_t>(k->Number()); |
| 8200 if (index < range) { | 8334 if (index < range) { |
| 8201 num_of_elements++; | 8335 indices->Add(index); |
| 8202 if (visitor) { | |
| 8203 visitor->visit(index, Handle<Object>(dict->ValueAt(j))); | |
| 8204 } | |
| 8205 } | 8336 } |
| 8206 } | 8337 } |
| 8207 } | 8338 } |
| 8208 break; | 8339 break; |
| 8209 } | 8340 } |
| 8341 default: { |
| 8342 int dense_elements_length; |
| 8343 switch (kind) { |
| 8344 case JSObject::EXTERNAL_PIXEL_ELEMENTS: { |
| 8345 dense_elements_length = |
| 8346 ExternalPixelArray::cast(object->elements())->length(); |
| 8347 break; |
| 8348 } |
| 8349 case JSObject::EXTERNAL_BYTE_ELEMENTS: { |
| 8350 dense_elements_length = |
| 8351 ExternalByteArray::cast(object->elements())->length(); |
| 8352 break; |
| 8353 } |
| 8354 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
| 8355 dense_elements_length = |
| 8356 ExternalUnsignedByteArray::cast(object->elements())->length(); |
| 8357 break; |
| 8358 } |
| 8359 case JSObject::EXTERNAL_SHORT_ELEMENTS: { |
| 8360 dense_elements_length = |
| 8361 ExternalShortArray::cast(object->elements())->length(); |
| 8362 break; |
| 8363 } |
| 8364 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { |
| 8365 dense_elements_length = |
| 8366 ExternalUnsignedShortArray::cast(object->elements())->length(); |
| 8367 break; |
| 8368 } |
| 8369 case JSObject::EXTERNAL_INT_ELEMENTS: { |
| 8370 dense_elements_length = |
| 8371 ExternalIntArray::cast(object->elements())->length(); |
| 8372 break; |
| 8373 } |
| 8374 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 8375 dense_elements_length = |
| 8376 ExternalUnsignedIntArray::cast(object->elements())->length(); |
| 8377 break; |
| 8378 } |
| 8379 case JSObject::EXTERNAL_FLOAT_ELEMENTS: { |
| 8380 dense_elements_length = |
| 8381 ExternalFloatArray::cast(object->elements())->length(); |
| 8382 break; |
| 8383 } |
| 8384 default: |
| 8385 UNREACHABLE(); |
| 8386 dense_elements_length = 0; |
| 8387 break; |
| 8388 } |
| 8389 uint32_t length = static_cast<uint32_t>(dense_elements_length); |
| 8390 if (range <= length) { |
| 8391 length = range; |
| 8392 // We will add all indices, so we might as well clear it first |
| 8393 // and avoid duplicates. |
| 8394 indices->Clear(); |
| 8395 } |
| 8396 for (uint32_t i = 0; i < length; i++) { |
| 8397 indices->Add(i); |
| 8398 } |
| 8399 if (length == range) return; // All indices accounted for already. |
| 8400 break; |
| 8401 } |
| 8402 } |
| 8403 |
| 8404 Handle<Object> prototype(object->GetPrototype()); |
| 8405 if (prototype->IsJSObject()) { |
| 8406 // The prototype will usually have no inherited element indices, |
| 8407 // but we have to check. |
| 8408 CollectElementIndices(Handle<JSObject>::cast(prototype), range, indices); |
| 8409 } |
| 8410 } |
| 8411 |
| 8412 |
| 8413 /** |
| 8414 * A helper function that visits elements of a JSArray in numerical |
| 8415 * order. |
| 8416 * |
| 8417 * The visitor argument called for each existing element in the array |
| 8418 * with the element index and the element's value. |
| 8419 * Afterwards it increments the base-index of the visitor by the array |
| 8420 * length. |
| 8421 * Returns false if any access threw an exception, otherwise true. |
| 8422 */ |
| 8423 static bool IterateElements(Handle<JSArray> receiver, |
| 8424 ArrayConcatVisitor* visitor) { |
| 8425 uint32_t length = static_cast<uint32_t>(receiver->length()->Number()); |
| 8426 switch (receiver->GetElementsKind()) { |
| 8427 case JSObject::FAST_ELEMENTS: { |
| 8428 // Run through the elements FixedArray and use HasElement and GetElement |
| 8429 // to check the prototype for missing elements. |
| 8430 Handle<FixedArray> elements(FixedArray::cast(receiver->elements())); |
| 8431 int fast_length = static_cast<int>(length); |
| 8432 ASSERT(fast_length <= elements->length()); |
| 8433 for (int j = 0; j < fast_length; j++) { |
| 8434 HandleScope loop_scope; |
| 8435 Handle<Object> element_value(elements->get(j)); |
| 8436 if (!element_value->IsTheHole()) { |
| 8437 visitor->visit(j, element_value); |
| 8438 } else if (receiver->HasElement(j)) { |
| 8439 // Call GetElement on receiver, not its prototype, or getters won't |
| 8440 // have the correct receiver. |
| 8441 element_value = GetElement(receiver, j); |
| 8442 if (element_value.is_null()) return false; |
| 8443 visitor->visit(j, element_value); |
| 8444 } |
| 8445 } |
| 8446 break; |
| 8447 } |
| 8448 case JSObject::DICTIONARY_ELEMENTS: { |
| 8449 Handle<NumberDictionary> dict(receiver->element_dictionary()); |
| 8450 List<uint32_t> indices(dict->Capacity() / 2); |
| 8451 // Collect all indices in the object and the prototypes less |
| 8452 // than length. This might introduce duplicates in the indices list. |
| 8453 CollectElementIndices(receiver, length, &indices); |
| 8454 indices.Sort(&compareUInt32); |
| 8455 int j = 0; |
| 8456 int n = indices.length(); |
| 8457 while (j < n) { |
| 8458 HandleScope loop_scope; |
| 8459 uint32_t index = indices[j]; |
| 8460 Handle<Object> element = GetElement(receiver, index); |
| 8461 if (element.is_null()) return false; |
| 8462 visitor->visit(index, element); |
| 8463 // Skip to next different index (i.e., omit duplicates). |
| 8464 do { |
| 8465 j++; |
| 8466 } while (j < n && indices[j] == index); |
| 8467 } |
| 8468 break; |
| 8469 } |
| 8470 case JSObject::EXTERNAL_PIXEL_ELEMENTS: { |
| 8471 Handle<ExternalPixelArray> pixels(ExternalPixelArray::cast( |
| 8472 receiver->elements())); |
| 8473 for (uint32_t j = 0; j < length; j++) { |
| 8474 Handle<Smi> e(Smi::FromInt(pixels->get(j))); |
| 8475 visitor->visit(j, e); |
| 8476 } |
| 8477 break; |
| 8478 } |
| 8479 case JSObject::EXTERNAL_BYTE_ELEMENTS: { |
| 8480 IterateExternalArrayElements<ExternalByteArray, int8_t>( |
| 8481 receiver, true, true, visitor); |
| 8482 break; |
| 8483 } |
| 8484 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
| 8485 IterateExternalArrayElements<ExternalUnsignedByteArray, uint8_t>( |
| 8486 receiver, true, true, visitor); |
| 8487 break; |
| 8488 } |
| 8489 case JSObject::EXTERNAL_SHORT_ELEMENTS: { |
| 8490 IterateExternalArrayElements<ExternalShortArray, int16_t>( |
| 8491 receiver, true, true, visitor); |
| 8492 break; |
| 8493 } |
| 8494 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: { |
| 8495 IterateExternalArrayElements<ExternalUnsignedShortArray, uint16_t>( |
| 8496 receiver, true, true, visitor); |
| 8497 break; |
| 8498 } |
| 8499 case JSObject::EXTERNAL_INT_ELEMENTS: { |
| 8500 IterateExternalArrayElements<ExternalIntArray, int32_t>( |
| 8501 receiver, true, false, visitor); |
| 8502 break; |
| 8503 } |
| 8504 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: { |
| 8505 IterateExternalArrayElements<ExternalUnsignedIntArray, uint32_t>( |
| 8506 receiver, true, false, visitor); |
| 8507 break; |
| 8508 } |
| 8509 case JSObject::EXTERNAL_FLOAT_ELEMENTS: { |
| 8510 IterateExternalArrayElements<ExternalFloatArray, float>( |
| 8511 receiver, false, false, visitor); |
| 8512 break; |
| 8513 } |
| 8210 default: | 8514 default: |
| 8211 UNREACHABLE(); | 8515 UNREACHABLE(); |
| 8212 break; | 8516 break; |
| 8213 } | 8517 } |
| 8214 | 8518 visitor->increase_index_offset(length); |
| 8215 return num_of_elements; | 8519 return true; |
| 8216 } | |
| 8217 | |
| 8218 | |
| 8219 /** | |
| 8220 * A helper function that visits elements of an Array object, and elements | |
| 8221 * on its prototypes. | |
| 8222 * | |
| 8223 * Elements on prototypes are visited first, and only elements whose indices | |
| 8224 * less than Array length are visited. | |
| 8225 * | |
| 8226 * If a ArrayConcatVisitor object is given, the visitor is called with | |
| 8227 * parameters, element's index + visitor_index_offset and the element. | |
| 8228 * | |
| 8229 * The returned number of elements is an upper bound on the actual number | |
| 8230 * of elements added. If the same element occurs in more than one object | |
| 8231 * in the array's prototype chain, it will be counted more than once, but | |
| 8232 * will only occur once in the result. | |
| 8233 */ | |
| 8234 static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array, | |
| 8235 ArrayConcatVisitor* visitor) { | |
| 8236 uint32_t range = static_cast<uint32_t>(array->length()->Number()); | |
| 8237 Handle<Object> obj = array; | |
| 8238 | |
| 8239 static const int kEstimatedPrototypes = 3; | |
| 8240 List< Handle<JSObject> > objects(kEstimatedPrototypes); | |
| 8241 | |
| 8242 // Visit prototype first. If an element on the prototype is shadowed by | |
| 8243 // the inheritor using the same index, the ArrayConcatVisitor visits | |
| 8244 // the prototype element before the shadowing element. | |
| 8245 // The visitor can simply overwrite the old value by new value using | |
| 8246 // the same index. This follows Array::concat semantics. | |
| 8247 while (!obj->IsNull()) { | |
| 8248 objects.Add(Handle<JSObject>::cast(obj)); | |
| 8249 obj = Handle<Object>(obj->GetPrototype()); | |
| 8250 } | |
| 8251 | |
| 8252 uint32_t nof_elements = 0; | |
| 8253 for (int i = objects.length() - 1; i >= 0; i--) { | |
| 8254 Handle<JSObject> obj = objects[i]; | |
| 8255 uint32_t encountered_elements = | |
| 8256 IterateElements(Handle<JSObject>::cast(obj), range, visitor); | |
| 8257 | |
| 8258 if (encountered_elements > JSObject::kMaxElementCount - nof_elements) { | |
| 8259 nof_elements = JSObject::kMaxElementCount; | |
| 8260 } else { | |
| 8261 nof_elements += encountered_elements; | |
| 8262 } | |
| 8263 } | |
| 8264 | |
| 8265 return nof_elements; | |
| 8266 } | |
| 8267 | |
| 8268 | |
| 8269 /** | |
| 8270 * A helper function of Runtime_ArrayConcat. | |
| 8271 * | |
| 8272 * The first argument is an Array of arrays and objects. It is the | |
| 8273 * same as the arguments array of Array::concat JS function. | |
| 8274 * | |
| 8275 * If an argument is an Array object, the function visits array | |
| 8276 * elements. If an argument is not an Array object, the function | |
| 8277 * visits the object as if it is an one-element array. | |
| 8278 * | |
| 8279 * If the result array index overflows 32-bit unsigned integer, the rounded | |
| 8280 * non-negative number is used as new length. For example, if one | |
| 8281 * array length is 2^32 - 1, second array length is 1, the | |
| 8282 * concatenated array length is 0. | |
| 8283 * TODO(lrn) Change length behavior to ECMAScript 5 specification (length | |
| 8284 * is one more than the last array index to get a value assigned). | |
| 8285 */ | |
| 8286 static uint32_t IterateArguments(Handle<JSArray> arguments, | |
| 8287 ArrayConcatVisitor* visitor) { | |
| 8288 uint32_t visited_elements = 0; | |
| 8289 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number()); | |
| 8290 | |
| 8291 for (uint32_t i = 0; i < num_of_args; i++) { | |
| 8292 Object *element; | |
| 8293 MaybeObject* maybe_element = arguments->GetElement(i); | |
| 8294 // This if() is not expected to fail, but we have the check in the | |
| 8295 // interest of hardening the runtime calls. | |
| 8296 if (maybe_element->ToObject(&element)) { | |
| 8297 Handle<Object> obj(element); | |
| 8298 if (obj->IsJSArray()) { | |
| 8299 Handle<JSArray> array = Handle<JSArray>::cast(obj); | |
| 8300 uint32_t len = static_cast<uint32_t>(array->length()->Number()); | |
| 8301 uint32_t nof_elements = | |
| 8302 IterateArrayAndPrototypeElements(array, visitor); | |
| 8303 // Total elements of array and its prototype chain can be more than | |
| 8304 // the array length, but ArrayConcat can only concatenate at most | |
| 8305 // the array length number of elements. We use the length as an estimate | |
| 8306 // for the actual number of elements added. | |
| 8307 uint32_t added_elements = (nof_elements > len) ? len : nof_elements; | |
| 8308 if (JSArray::kMaxElementCount - visited_elements < added_elements) { | |
| 8309 visited_elements = JSArray::kMaxElementCount; | |
| 8310 } else { | |
| 8311 visited_elements += added_elements; | |
| 8312 } | |
| 8313 if (visitor) visitor->increase_index_offset(len); | |
| 8314 } else { | |
| 8315 if (visitor) { | |
| 8316 visitor->visit(0, obj); | |
| 8317 visitor->increase_index_offset(1); | |
| 8318 } | |
| 8319 if (visited_elements < JSArray::kMaxElementCount) { | |
| 8320 visited_elements++; | |
| 8321 } | |
| 8322 } | |
| 8323 } | |
| 8324 } | |
| 8325 return visited_elements; | |
| 8326 } | 8520 } |
| 8327 | 8521 |
| 8328 | 8522 |
| 8329 /** | 8523 /** |
| 8330 * Array::concat implementation. | 8524 * Array::concat implementation. |
| 8331 * See ECMAScript 262, 15.4.4.4. | 8525 * See ECMAScript 262, 15.4.4.4. |
| 8332 * TODO(lrn): Fix non-compliance for very large concatenations and update to | 8526 * TODO(581): Fix non-compliance for very large concatenations and update to |
| 8333 * following the ECMAScript 5 specification. | 8527 * following the ECMAScript 5 specification. |
| 8334 */ | 8528 */ |
| 8335 static MaybeObject* Runtime_ArrayConcat(Arguments args) { | 8529 static MaybeObject* Runtime_ArrayConcat(Arguments args) { |
| 8336 ASSERT(args.length() == 1); | 8530 ASSERT(args.length() == 1); |
| 8337 HandleScope handle_scope; | 8531 HandleScope handle_scope; |
| 8338 | 8532 |
| 8339 CONVERT_CHECKED(JSArray, arg_arrays, args[0]); | 8533 CONVERT_ARG_CHECKED(JSArray, arguments, 0); |
| 8340 Handle<JSArray> arguments(arg_arrays); | 8534 int argument_count = static_cast<int>(arguments->length()->Number()); |
| 8341 | 8535 RUNTIME_ASSERT(arguments->HasFastElements()); |
| 8342 // Pass 1: estimate the number of elements of the result | 8536 Handle<FixedArray> elements(FixedArray::cast(arguments->elements())); |
| 8343 // (it could be more than real numbers if prototype has elements). | 8537 |
| 8344 uint32_t result_length = 0; | 8538 // Pass 1: estimate the length and number of elements of the result. |
| 8345 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number()); | 8539 // The actual length can be larger if any of the arguments have getters |
| 8346 | 8540 // that mutate other arguments (but will otherwise be precise). |
| 8347 { AssertNoAllocation nogc; | 8541 // The number of elements is precise if there are no inherited elements. |
| 8348 for (uint32_t i = 0; i < num_of_args; i++) { | 8542 |
| 8349 Object* obj; | 8543 uint32_t estimate_result_length = 0; |
| 8350 MaybeObject* maybe_object = arguments->GetElement(i); | 8544 uint32_t estimate_nof_elements = 0; |
| 8351 // This if() is not expected to fail, but we have the check in the | 8545 { |
| 8352 // interest of hardening the runtime calls. | 8546 for (int i = 0; i < argument_count; i++) { |
| 8353 if (maybe_object->ToObject(&obj)) { | 8547 HandleScope loop_scope; |
| 8354 uint32_t length_estimate; | 8548 Handle<Object> obj(elements->get(i)); |
| 8355 if (obj->IsJSArray()) { | 8549 uint32_t length_estimate; |
| 8356 length_estimate = | 8550 uint32_t element_estimate; |
| 8357 static_cast<uint32_t>(JSArray::cast(obj)->length()->Number()); | 8551 if (obj->IsJSArray()) { |
| 8358 } else { | 8552 Handle<JSArray> array(Handle<JSArray>::cast(obj)); |
| 8359 length_estimate = 1; | 8553 length_estimate = |
| 8360 } | 8554 static_cast<uint32_t>(array->length()->Number()); |
| 8361 if (JSObject::kMaxElementCount - result_length < length_estimate) { | 8555 element_estimate = |
| 8362 result_length = JSObject::kMaxElementCount; | 8556 EstimateElementCount(array); |
| 8363 break; | 8557 } else { |
| 8364 } | 8558 length_estimate = 1; |
| 8365 result_length += length_estimate; | 8559 element_estimate = 1; |
| 8366 } | 8560 } |
| 8367 } | 8561 // Avoid overflows by capping at kMaxElementCount. |
| 8368 } | 8562 if (JSObject::kMaxElementCount - estimate_result_length < |
| 8369 | 8563 length_estimate) { |
| 8370 // Allocate an empty array, will set map, length, and content later. | 8564 estimate_result_length = JSObject::kMaxElementCount; |
| 8371 Handle<JSArray> result = Factory::NewJSArray(0); | 8565 } else { |
| 8372 | 8566 estimate_result_length += length_estimate; |
| 8373 uint32_t estimate_nof_elements = IterateArguments(arguments, NULL); | 8567 } |
| 8568 if (JSObject::kMaxElementCount - estimate_nof_elements < |
| 8569 element_estimate) { |
| 8570 estimate_nof_elements = JSObject::kMaxElementCount; |
| 8571 } else { |
| 8572 estimate_nof_elements += element_estimate; |
| 8573 } |
| 8574 } |
| 8575 } |
| 8576 |
| 8374 // If estimated number of elements is more than half of length, a | 8577 // If estimated number of elements is more than half of length, a |
| 8375 // fixed array (fast case) is more time and space-efficient than a | 8578 // fixed array (fast case) is more time and space-efficient than a |
| 8376 // dictionary. | 8579 // dictionary. |
| 8377 bool fast_case = (estimate_nof_elements * 2) >= result_length; | 8580 bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length; |
| 8378 | 8581 |
| 8379 Handle<Map> map; | |
| 8380 Handle<FixedArray> storage; | 8582 Handle<FixedArray> storage; |
| 8381 if (fast_case) { | 8583 if (fast_case) { |
| 8382 // The backing storage array must have non-existing elements to | 8584 // The backing storage array must have non-existing elements to |
| 8383 // preserve holes across concat operations. | 8585 // preserve holes across concat operations. |
| 8384 map = Factory::GetFastElementsMap(Handle<Map>(result->map())); | 8586 storage = Factory::NewFixedArrayWithHoles(estimate_result_length); |
| 8385 storage = Factory::NewFixedArrayWithHoles(result_length); | |
| 8386 } else { | 8587 } else { |
| 8387 map = Factory::GetSlowElementsMap(Handle<Map>(result->map())); | |
| 8388 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate | 8588 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate |
| 8389 uint32_t at_least_space_for = estimate_nof_elements + | 8589 uint32_t at_least_space_for = estimate_nof_elements + |
| 8390 (estimate_nof_elements >> 2); | 8590 (estimate_nof_elements >> 2); |
| 8391 storage = Handle<FixedArray>::cast( | 8591 storage = Handle<FixedArray>::cast( |
| 8392 Factory::NewNumberDictionary(at_least_space_for)); | 8592 Factory::NewNumberDictionary(at_least_space_for)); |
| 8393 } | 8593 } |
| 8394 | 8594 |
| 8395 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length)); | 8595 ArrayConcatVisitor visitor(storage, fast_case); |
| 8396 | 8596 |
| 8397 ArrayConcatVisitor visitor(storage, result_length, fast_case); | 8597 for (int i = 0; i < argument_count; i++) { |
| 8598 Handle<Object> obj(elements->get(i)); |
| 8599 if (obj->IsJSArray()) { |
| 8600 Handle<JSArray> array = Handle<JSArray>::cast(obj); |
| 8601 if (!IterateElements(array, &visitor)) { |
| 8602 return Failure::Exception(); |
| 8603 } |
| 8604 } else { |
| 8605 visitor.visit(0, obj); |
| 8606 visitor.increase_index_offset(1); |
| 8607 } |
| 8608 } |
| 8398 | 8609 |
| 8399 IterateArguments(arguments, &visitor); | 8610 return *visitor.ToArray(); |
| 8400 | |
| 8401 // Please note: | |
| 8402 // - the storage might have been changed in the visitor; | |
| 8403 // - the map and the storage must be set together to avoid breaking | |
| 8404 // the invariant that the map describes the array's elements. | |
| 8405 result->set_map(*map); | |
| 8406 result->set_length(*len); | |
| 8407 result->set_elements(*visitor.storage()); | |
| 8408 | |
| 8409 return *result; | |
| 8410 } | 8611 } |
| 8411 | 8612 |
| 8412 | 8613 |
| 8413 // This will not allocate (flatten the string), but it may run | 8614 // This will not allocate (flatten the string), but it may run |
| 8414 // very slowly for very deeply nested ConsStrings. For debugging use only. | 8615 // very slowly for very deeply nested ConsStrings. For debugging use only. |
| 8415 static MaybeObject* Runtime_GlobalPrint(Arguments args) { | 8616 static MaybeObject* Runtime_GlobalPrint(Arguments args) { |
| 8416 NoHandleAllocation ha; | 8617 NoHandleAllocation ha; |
| 8417 ASSERT(args.length() == 1); | 8618 ASSERT(args.length() == 1); |
| 8418 | 8619 |
| 8419 CONVERT_CHECKED(String, string, args[0]); | 8620 CONVERT_CHECKED(String, string, args[0]); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8490 Handle<Object> key2 = args.at<Object>(2); | 8691 Handle<Object> key2 = args.at<Object>(2); |
| 8491 | 8692 |
| 8492 uint32_t index1, index2; | 8693 uint32_t index1, index2; |
| 8493 if (!key1->ToArrayIndex(&index1) | 8694 if (!key1->ToArrayIndex(&index1) |
| 8494 || !key2->ToArrayIndex(&index2)) { | 8695 || !key2->ToArrayIndex(&index2)) { |
| 8495 return Top::ThrowIllegalOperation(); | 8696 return Top::ThrowIllegalOperation(); |
| 8496 } | 8697 } |
| 8497 | 8698 |
| 8498 Handle<JSObject> jsobject = Handle<JSObject>::cast(object); | 8699 Handle<JSObject> jsobject = Handle<JSObject>::cast(object); |
| 8499 Handle<Object> tmp1 = GetElement(jsobject, index1); | 8700 Handle<Object> tmp1 = GetElement(jsobject, index1); |
| 8701 RETURN_IF_EMPTY_HANDLE(tmp1); |
| 8500 Handle<Object> tmp2 = GetElement(jsobject, index2); | 8702 Handle<Object> tmp2 = GetElement(jsobject, index2); |
| 8703 RETURN_IF_EMPTY_HANDLE(tmp2); |
| 8501 | 8704 |
| 8502 SetElement(jsobject, index1, tmp2); | 8705 RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index1, tmp2, kStrictMode)); |
| 8503 SetElement(jsobject, index2, tmp1); | 8706 RETURN_IF_EMPTY_HANDLE(SetElement(jsobject, index2, tmp1, kStrictMode)); |
| 8504 | 8707 |
| 8505 return Heap::undefined_value(); | 8708 return Heap::undefined_value(); |
| 8506 } | 8709 } |
| 8507 | 8710 |
| 8508 | 8711 |
| 8509 // Returns an array that tells you where in the [0, length) interval an array | 8712 // Returns an array that tells you where in the [0, length) interval an array |
| 8510 // might have elements. Can either return keys (positive integers) or | 8713 // might have elements. Can either return keys (positive integers) or |
| 8511 // intervals (pair of a negative integer (-start-1) followed by a | 8714 // intervals (pair of a negative integer (-start-1) followed by a |
| 8512 // positive (length)) or undefined values. | 8715 // positive (length)) or undefined values. |
| 8513 // Intervals can span over some keys that are not in the object. | 8716 // Intervals can span over some keys that are not in the object. |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9056 | 9259 |
| 9057 // Now advance to the arguments adapter frame (if any). It contains all | 9260 // Now advance to the arguments adapter frame (if any). It contains all |
| 9058 // the provided parameters whereas the function frame always have the number | 9261 // the provided parameters whereas the function frame always have the number |
| 9059 // of arguments matching the functions parameters. The rest of the | 9262 // of arguments matching the functions parameters. The rest of the |
| 9060 // information (except for what is collected above) is the same. | 9263 // information (except for what is collected above) is the same. |
| 9061 it.AdvanceToArgumentsFrame(); | 9264 it.AdvanceToArgumentsFrame(); |
| 9062 | 9265 |
| 9063 // Find the number of arguments to fill. At least fill the number of | 9266 // Find the number of arguments to fill. At least fill the number of |
| 9064 // parameters for the function and fill more if more parameters are provided. | 9267 // parameters for the function and fill more if more parameters are provided. |
| 9065 int argument_count = info.number_of_parameters(); | 9268 int argument_count = info.number_of_parameters(); |
| 9066 if (argument_count < it.frame()->GetProvidedParametersCount()) { | 9269 if (argument_count < it.frame()->ComputeParametersCount()) { |
| 9067 argument_count = it.frame()->GetProvidedParametersCount(); | 9270 argument_count = it.frame()->ComputeParametersCount(); |
| 9068 } | 9271 } |
| 9069 | 9272 |
| 9070 // Calculate the size of the result. | 9273 // Calculate the size of the result. |
| 9071 int details_size = kFrameDetailsFirstDynamicIndex + | 9274 int details_size = kFrameDetailsFirstDynamicIndex + |
| 9072 2 * (argument_count + info.NumberOfLocals()) + | 9275 2 * (argument_count + info.NumberOfLocals()) + |
| 9073 (at_return ? 1 : 0); | 9276 (at_return ? 1 : 0); |
| 9074 Handle<FixedArray> details = Factory::NewFixedArray(details_size); | 9277 Handle<FixedArray> details = Factory::NewFixedArray(details_size); |
| 9075 | 9278 |
| 9076 // Add the frame id. | 9279 // Add the frame id. |
| 9077 details->set(kFrameDetailsFrameIdIndex, *frame_id); | 9280 details->set(kFrameDetailsFrameIdIndex, *frame_id); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9114 } else { | 9317 } else { |
| 9115 details->set(details_index++, Heap::undefined_value()); | 9318 details->set(details_index++, Heap::undefined_value()); |
| 9116 } | 9319 } |
| 9117 | 9320 |
| 9118 // Parameter value. If we are inspecting an optimized frame, use | 9321 // Parameter value. If we are inspecting an optimized frame, use |
| 9119 // undefined as the value. | 9322 // undefined as the value. |
| 9120 // | 9323 // |
| 9121 // TODO(3141533): We should be able to get the actual parameter | 9324 // TODO(3141533): We should be able to get the actual parameter |
| 9122 // value for optimized frames. | 9325 // value for optimized frames. |
| 9123 if (!is_optimized_frame && | 9326 if (!is_optimized_frame && |
| 9124 (i < it.frame()->GetProvidedParametersCount())) { | 9327 (i < it.frame()->ComputeParametersCount())) { |
| 9125 details->set(details_index++, it.frame()->GetParameter(i)); | 9328 details->set(details_index++, it.frame()->GetParameter(i)); |
| 9126 } else { | 9329 } else { |
| 9127 details->set(details_index++, Heap::undefined_value()); | 9330 details->set(details_index++, Heap::undefined_value()); |
| 9128 } | 9331 } |
| 9129 } | 9332 } |
| 9130 | 9333 |
| 9131 // Add locals name and value from the temporary copy from the function frame. | 9334 // Add locals name and value from the temporary copy from the function frame. |
| 9132 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { | 9335 for (int i = 0; i < info.NumberOfLocals() * 2; i++) { |
| 9133 details->set(details_index++, locals->get(i)); | 9336 details->set(details_index++, locals->get(i)); |
| 9134 } | 9337 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9171 i < scope_info.number_of_context_slots(); | 9374 i < scope_info.number_of_context_slots(); |
| 9172 i++) { | 9375 i++) { |
| 9173 int context_index = serialized_scope_info->ContextSlotIndex( | 9376 int context_index = serialized_scope_info->ContextSlotIndex( |
| 9174 *scope_info.context_slot_name(i), NULL); | 9377 *scope_info.context_slot_name(i), NULL); |
| 9175 | 9378 |
| 9176 // Don't include the arguments shadow (.arguments) context variable. | 9379 // Don't include the arguments shadow (.arguments) context variable. |
| 9177 if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) { | 9380 if (*scope_info.context_slot_name(i) != Heap::arguments_shadow_symbol()) { |
| 9178 RETURN_IF_EMPTY_HANDLE_VALUE( | 9381 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9179 SetProperty(scope_object, | 9382 SetProperty(scope_object, |
| 9180 scope_info.context_slot_name(i), | 9383 scope_info.context_slot_name(i), |
| 9181 Handle<Object>(context->get(context_index)), NONE), | 9384 Handle<Object>(context->get(context_index)), |
| 9385 NONE, |
| 9386 kNonStrictMode), |
| 9182 false); | 9387 false); |
| 9183 } | 9388 } |
| 9184 } | 9389 } |
| 9185 | 9390 |
| 9186 return true; | 9391 return true; |
| 9187 } | 9392 } |
| 9188 | 9393 |
| 9189 | 9394 |
| 9190 // Create a plain JSObject which materializes the local scope for the specified | 9395 // Create a plain JSObject which materializes the local scope for the specified |
| 9191 // frame. | 9396 // frame. |
| 9192 static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) { | 9397 static Handle<JSObject> MaterializeLocalScope(JavaScriptFrame* frame) { |
| 9193 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 9398 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
| 9194 Handle<SharedFunctionInfo> shared(function->shared()); | 9399 Handle<SharedFunctionInfo> shared(function->shared()); |
| 9195 Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); | 9400 Handle<SerializedScopeInfo> serialized_scope_info(shared->scope_info()); |
| 9196 ScopeInfo<> scope_info(*serialized_scope_info); | 9401 ScopeInfo<> scope_info(*serialized_scope_info); |
| 9197 | 9402 |
| 9198 // Allocate and initialize a JSObject with all the arguments, stack locals | 9403 // Allocate and initialize a JSObject with all the arguments, stack locals |
| 9199 // heap locals and extension properties of the debugged function. | 9404 // heap locals and extension properties of the debugged function. |
| 9200 Handle<JSObject> local_scope = Factory::NewJSObject(Top::object_function()); | 9405 Handle<JSObject> local_scope = Factory::NewJSObject(Top::object_function()); |
| 9201 | 9406 |
| 9202 // First fill all parameters. | 9407 // First fill all parameters. |
| 9203 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { | 9408 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { |
| 9204 RETURN_IF_EMPTY_HANDLE_VALUE( | 9409 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9205 SetProperty(local_scope, | 9410 SetProperty(local_scope, |
| 9206 scope_info.parameter_name(i), | 9411 scope_info.parameter_name(i), |
| 9207 Handle<Object>(frame->GetParameter(i)), NONE), | 9412 Handle<Object>(frame->GetParameter(i)), |
| 9413 NONE, |
| 9414 kNonStrictMode), |
| 9208 Handle<JSObject>()); | 9415 Handle<JSObject>()); |
| 9209 } | 9416 } |
| 9210 | 9417 |
| 9211 // Second fill all stack locals. | 9418 // Second fill all stack locals. |
| 9212 for (int i = 0; i < scope_info.number_of_stack_slots(); i++) { | 9419 for (int i = 0; i < scope_info.number_of_stack_slots(); i++) { |
| 9213 RETURN_IF_EMPTY_HANDLE_VALUE( | 9420 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9214 SetProperty(local_scope, | 9421 SetProperty(local_scope, |
| 9215 scope_info.stack_slot_name(i), | 9422 scope_info.stack_slot_name(i), |
| 9216 Handle<Object>(frame->GetExpression(i)), NONE), | 9423 Handle<Object>(frame->GetExpression(i)), |
| 9424 NONE, |
| 9425 kNonStrictMode), |
| 9217 Handle<JSObject>()); | 9426 Handle<JSObject>()); |
| 9218 } | 9427 } |
| 9219 | 9428 |
| 9220 // Third fill all context locals. | 9429 // Third fill all context locals. |
| 9221 Handle<Context> frame_context(Context::cast(frame->context())); | 9430 Handle<Context> frame_context(Context::cast(frame->context())); |
| 9222 Handle<Context> function_context(frame_context->fcontext()); | 9431 Handle<Context> function_context(frame_context->fcontext()); |
| 9223 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, | 9432 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, |
| 9224 function_context, local_scope)) { | 9433 function_context, local_scope)) { |
| 9225 return Handle<JSObject>(); | 9434 return Handle<JSObject>(); |
| 9226 } | 9435 } |
| 9227 | 9436 |
| 9228 // Finally copy any properties from the function context extension. This will | 9437 // Finally copy any properties from the function context extension. This will |
| 9229 // be variables introduced by eval. | 9438 // be variables introduced by eval. |
| 9230 if (function_context->closure() == *function) { | 9439 if (function_context->closure() == *function) { |
| 9231 if (function_context->has_extension() && | 9440 if (function_context->has_extension() && |
| 9232 !function_context->IsGlobalContext()) { | 9441 !function_context->IsGlobalContext()) { |
| 9233 Handle<JSObject> ext(JSObject::cast(function_context->extension())); | 9442 Handle<JSObject> ext(JSObject::cast(function_context->extension())); |
| 9234 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); | 9443 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); |
| 9235 for (int i = 0; i < keys->length(); i++) { | 9444 for (int i = 0; i < keys->length(); i++) { |
| 9236 // Names of variables introduced by eval are strings. | 9445 // Names of variables introduced by eval are strings. |
| 9237 ASSERT(keys->get(i)->IsString()); | 9446 ASSERT(keys->get(i)->IsString()); |
| 9238 Handle<String> key(String::cast(keys->get(i))); | 9447 Handle<String> key(String::cast(keys->get(i))); |
| 9239 RETURN_IF_EMPTY_HANDLE_VALUE( | 9448 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9240 SetProperty(local_scope, key, GetProperty(ext, key), NONE), | 9449 SetProperty(local_scope, |
| 9450 key, |
| 9451 GetProperty(ext, key), |
| 9452 NONE, |
| 9453 kNonStrictMode), |
| 9241 Handle<JSObject>()); | 9454 Handle<JSObject>()); |
| 9242 } | 9455 } |
| 9243 } | 9456 } |
| 9244 } | 9457 } |
| 9245 return local_scope; | 9458 return local_scope; |
| 9246 } | 9459 } |
| 9247 | 9460 |
| 9248 | 9461 |
| 9249 // Create a plain JSObject which materializes the closure content for the | 9462 // Create a plain JSObject which materializes the closure content for the |
| 9250 // context. | 9463 // context. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 9268 // object. | 9481 // object. |
| 9269 Handle<JSObject> arguments_shadow( | 9482 Handle<JSObject> arguments_shadow( |
| 9270 JSObject::cast(context->get(arguments_shadow_index))); | 9483 JSObject::cast(context->get(arguments_shadow_index))); |
| 9271 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { | 9484 for (int i = 0; i < scope_info.number_of_parameters(); ++i) { |
| 9272 // We don't expect exception-throwing getters on the arguments shadow. | 9485 // We don't expect exception-throwing getters on the arguments shadow. |
| 9273 Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked(); | 9486 Object* element = arguments_shadow->GetElement(i)->ToObjectUnchecked(); |
| 9274 RETURN_IF_EMPTY_HANDLE_VALUE( | 9487 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9275 SetProperty(closure_scope, | 9488 SetProperty(closure_scope, |
| 9276 scope_info.parameter_name(i), | 9489 scope_info.parameter_name(i), |
| 9277 Handle<Object>(element), | 9490 Handle<Object>(element), |
| 9278 NONE), | 9491 NONE, |
| 9492 kNonStrictMode), |
| 9279 Handle<JSObject>()); | 9493 Handle<JSObject>()); |
| 9280 } | 9494 } |
| 9281 } | 9495 } |
| 9282 | 9496 |
| 9283 // Fill all context locals to the context extension. | 9497 // Fill all context locals to the context extension. |
| 9284 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, | 9498 if (!CopyContextLocalsToScopeObject(serialized_scope_info, scope_info, |
| 9285 context, closure_scope)) { | 9499 context, closure_scope)) { |
| 9286 return Handle<JSObject>(); | 9500 return Handle<JSObject>(); |
| 9287 } | 9501 } |
| 9288 | 9502 |
| 9289 // Finally copy any properties from the function context extension. This will | 9503 // Finally copy any properties from the function context extension. This will |
| 9290 // be variables introduced by eval. | 9504 // be variables introduced by eval. |
| 9291 if (context->has_extension()) { | 9505 if (context->has_extension()) { |
| 9292 Handle<JSObject> ext(JSObject::cast(context->extension())); | 9506 Handle<JSObject> ext(JSObject::cast(context->extension())); |
| 9293 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); | 9507 Handle<FixedArray> keys = GetKeysInFixedArrayFor(ext, INCLUDE_PROTOS); |
| 9294 for (int i = 0; i < keys->length(); i++) { | 9508 for (int i = 0; i < keys->length(); i++) { |
| 9295 // Names of variables introduced by eval are strings. | 9509 // Names of variables introduced by eval are strings. |
| 9296 ASSERT(keys->get(i)->IsString()); | 9510 ASSERT(keys->get(i)->IsString()); |
| 9297 Handle<String> key(String::cast(keys->get(i))); | 9511 Handle<String> key(String::cast(keys->get(i))); |
| 9298 RETURN_IF_EMPTY_HANDLE_VALUE( | 9512 RETURN_IF_EMPTY_HANDLE_VALUE( |
| 9299 SetProperty(closure_scope, key, GetProperty(ext, key), NONE), | 9513 SetProperty(closure_scope, |
| 9514 key, |
| 9515 GetProperty(ext, key), |
| 9516 NONE, |
| 9517 kNonStrictMode), |
| 9300 Handle<JSObject>()); | 9518 Handle<JSObject>()); |
| 9301 } | 9519 } |
| 9302 } | 9520 } |
| 9303 | 9521 |
| 9304 return closure_scope; | 9522 return closure_scope; |
| 9305 } | 9523 } |
| 9306 | 9524 |
| 9307 | 9525 |
| 9308 // Iterate over the actual scopes visible from a stack frame. All scopes are | 9526 // Iterate over the actual scopes visible from a stack frame. All scopes are |
| 9309 // backed by an actual context except the local scope, which is inserted | 9527 // backed by an actual context except the local scope, which is inserted |
| (...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9979 } | 10197 } |
| 9980 } | 10198 } |
| 9981 | 10199 |
| 9982 if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) { | 10200 if (sinfo->number_of_context_slots() > Context::MIN_CONTEXT_SLOTS) { |
| 9983 index = scope_info->ContextSlotIndex(Heap::arguments_symbol(), NULL); | 10201 index = scope_info->ContextSlotIndex(Heap::arguments_symbol(), NULL); |
| 9984 if (index != -1) { | 10202 if (index != -1) { |
| 9985 return Handle<Object>(function_context->get(index)); | 10203 return Handle<Object>(function_context->get(index)); |
| 9986 } | 10204 } |
| 9987 } | 10205 } |
| 9988 | 10206 |
| 9989 const int length = frame->GetProvidedParametersCount(); | 10207 const int length = frame->ComputeParametersCount(); |
| 9990 Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length); | 10208 Handle<JSObject> arguments = Factory::NewArgumentsObject(function, length); |
| 9991 Handle<FixedArray> array = Factory::NewFixedArray(length); | 10209 Handle<FixedArray> array = Factory::NewFixedArray(length); |
| 9992 | 10210 |
| 9993 AssertNoAllocation no_gc; | 10211 AssertNoAllocation no_gc; |
| 9994 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); | 10212 WriteBarrierMode mode = array->GetWriteBarrierMode(no_gc); |
| 9995 for (int i = 0; i < length; i++) { | 10213 for (int i = 0; i < length; i++) { |
| 9996 array->set(i, frame->GetParameter(i), mode); | 10214 array->set(i, frame->GetParameter(i), mode); |
| 9997 } | 10215 } |
| 9998 arguments->set_elements(*array); | 10216 arguments->set_elements(*array); |
| 9999 return arguments; | 10217 return arguments; |
| (...skipping 767 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10767 | 10985 |
| 10768 | 10986 |
| 10769 // Gets the current heap usage. | 10987 // Gets the current heap usage. |
| 10770 static MaybeObject* Runtime_GetHeapUsage(Arguments args) { | 10988 static MaybeObject* Runtime_GetHeapUsage(Arguments args) { |
| 10771 int usage = static_cast<int>(Heap::SizeOfObjects()); | 10989 int usage = static_cast<int>(Heap::SizeOfObjects()); |
| 10772 if (!Smi::IsValid(usage)) { | 10990 if (!Smi::IsValid(usage)) { |
| 10773 return *Factory::NewNumberFromInt(usage); | 10991 return *Factory::NewNumberFromInt(usage); |
| 10774 } | 10992 } |
| 10775 return Smi::FromInt(usage); | 10993 return Smi::FromInt(usage); |
| 10776 } | 10994 } |
| 10995 |
| 10996 |
| 10997 // Captures a live object list from the present heap. |
| 10998 static MaybeObject* Runtime_HasLOLEnabled(Arguments args) { |
| 10999 #ifdef LIVE_OBJECT_LIST |
| 11000 return Heap::true_value(); |
| 11001 #else |
| 11002 return Heap::false_value(); |
| 11003 #endif |
| 11004 } |
| 11005 |
| 11006 |
| 11007 // Captures a live object list from the present heap. |
| 11008 static MaybeObject* Runtime_CaptureLOL(Arguments args) { |
| 11009 #ifdef LIVE_OBJECT_LIST |
| 11010 return LiveObjectList::Capture(); |
| 11011 #else |
| 11012 return Heap::undefined_value(); |
| 11013 #endif |
| 11014 } |
| 11015 |
| 11016 |
| 11017 // Deletes the specified live object list. |
| 11018 static MaybeObject* Runtime_DeleteLOL(Arguments args) { |
| 11019 #ifdef LIVE_OBJECT_LIST |
| 11020 CONVERT_SMI_CHECKED(id, args[0]); |
| 11021 bool success = LiveObjectList::Delete(id); |
| 11022 return success ? Heap::true_value() : Heap::false_value(); |
| 11023 #else |
| 11024 return Heap::undefined_value(); |
| 11025 #endif |
| 11026 } |
| 11027 |
| 11028 |
| 11029 // Generates the response to a debugger request for a dump of the objects |
| 11030 // contained in the difference between the captured live object lists |
| 11031 // specified by id1 and id2. |
| 11032 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be |
| 11033 // dumped. |
| 11034 static MaybeObject* Runtime_DumpLOL(Arguments args) { |
| 11035 #ifdef LIVE_OBJECT_LIST |
| 11036 HandleScope scope; |
| 11037 CONVERT_SMI_CHECKED(id1, args[0]); |
| 11038 CONVERT_SMI_CHECKED(id2, args[1]); |
| 11039 CONVERT_SMI_CHECKED(start, args[2]); |
| 11040 CONVERT_SMI_CHECKED(count, args[3]); |
| 11041 CONVERT_ARG_CHECKED(JSObject, filter_obj, 4); |
| 11042 EnterDebugger enter_debugger; |
| 11043 return LiveObjectList::Dump(id1, id2, start, count, filter_obj); |
| 11044 #else |
| 11045 return Heap::undefined_value(); |
| 11046 #endif |
| 11047 } |
| 11048 |
| 11049 |
| 11050 // Gets the specified object as requested by the debugger. |
| 11051 // This is only used for obj ids shown in live object lists. |
| 11052 static MaybeObject* Runtime_GetLOLObj(Arguments args) { |
| 11053 #ifdef LIVE_OBJECT_LIST |
| 11054 CONVERT_SMI_CHECKED(obj_id, args[0]); |
| 11055 Object* result = LiveObjectList::GetObj(obj_id); |
| 11056 return result; |
| 11057 #else |
| 11058 return Heap::undefined_value(); |
| 11059 #endif |
| 11060 } |
| 11061 |
| 11062 |
| 11063 // Gets the obj id for the specified address if valid. |
| 11064 // This is only used for obj ids shown in live object lists. |
| 11065 static MaybeObject* Runtime_GetLOLObjId(Arguments args) { |
| 11066 #ifdef LIVE_OBJECT_LIST |
| 11067 HandleScope scope; |
| 11068 CONVERT_ARG_CHECKED(String, address, 0); |
| 11069 Object* result = LiveObjectList::GetObjId(address); |
| 11070 return result; |
| 11071 #else |
| 11072 return Heap::undefined_value(); |
| 11073 #endif |
| 11074 } |
| 11075 |
| 11076 |
| 11077 // Gets the retainers that references the specified object alive. |
| 11078 static MaybeObject* Runtime_GetLOLObjRetainers(Arguments args) { |
| 11079 #ifdef LIVE_OBJECT_LIST |
| 11080 HandleScope scope; |
| 11081 CONVERT_SMI_CHECKED(obj_id, args[0]); |
| 11082 RUNTIME_ASSERT(args[1]->IsUndefined() || args[1]->IsJSObject()); |
| 11083 RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsBoolean()); |
| 11084 RUNTIME_ASSERT(args[3]->IsUndefined() || args[3]->IsSmi()); |
| 11085 RUNTIME_ASSERT(args[4]->IsUndefined() || args[4]->IsSmi()); |
| 11086 CONVERT_ARG_CHECKED(JSObject, filter_obj, 5); |
| 11087 |
| 11088 Handle<JSObject> instance_filter; |
| 11089 if (args[1]->IsJSObject()) { |
| 11090 instance_filter = args.at<JSObject>(1); |
| 11091 } |
| 11092 bool verbose = false; |
| 11093 if (args[2]->IsBoolean()) { |
| 11094 verbose = args[2]->IsTrue(); |
| 11095 } |
| 11096 int start = 0; |
| 11097 if (args[3]->IsSmi()) { |
| 11098 start = Smi::cast(args[3])->value(); |
| 11099 } |
| 11100 int limit = Smi::kMaxValue; |
| 11101 if (args[4]->IsSmi()) { |
| 11102 limit = Smi::cast(args[4])->value(); |
| 11103 } |
| 11104 |
| 11105 return LiveObjectList::GetObjRetainers(obj_id, |
| 11106 instance_filter, |
| 11107 verbose, |
| 11108 start, |
| 11109 limit, |
| 11110 filter_obj); |
| 11111 #else |
| 11112 return Heap::undefined_value(); |
| 11113 #endif |
| 11114 } |
| 11115 |
| 11116 |
| 11117 // Gets the reference path between 2 objects. |
| 11118 static MaybeObject* Runtime_GetLOLPath(Arguments args) { |
| 11119 #ifdef LIVE_OBJECT_LIST |
| 11120 HandleScope scope; |
| 11121 CONVERT_SMI_CHECKED(obj_id1, args[0]); |
| 11122 CONVERT_SMI_CHECKED(obj_id2, args[1]); |
| 11123 RUNTIME_ASSERT(args[2]->IsUndefined() || args[2]->IsJSObject()); |
| 11124 |
| 11125 Handle<JSObject> instance_filter; |
| 11126 if (args[2]->IsJSObject()) { |
| 11127 instance_filter = args.at<JSObject>(2); |
| 11128 } |
| 11129 |
| 11130 Object* result = |
| 11131 LiveObjectList::GetPath(obj_id1, obj_id2, instance_filter); |
| 11132 return result; |
| 11133 #else |
| 11134 return Heap::undefined_value(); |
| 11135 #endif |
| 11136 } |
| 11137 |
| 11138 |
| 11139 // Generates the response to a debugger request for a list of all |
| 11140 // previously captured live object lists. |
| 11141 static MaybeObject* Runtime_InfoLOL(Arguments args) { |
| 11142 #ifdef LIVE_OBJECT_LIST |
| 11143 CONVERT_SMI_CHECKED(start, args[0]); |
| 11144 CONVERT_SMI_CHECKED(count, args[1]); |
| 11145 return LiveObjectList::Info(start, count); |
| 11146 #else |
| 11147 return Heap::undefined_value(); |
| 11148 #endif |
| 11149 } |
| 11150 |
| 11151 |
| 11152 // Gets a dump of the specified object as requested by the debugger. |
| 11153 // This is only used for obj ids shown in live object lists. |
| 11154 static MaybeObject* Runtime_PrintLOLObj(Arguments args) { |
| 11155 #ifdef LIVE_OBJECT_LIST |
| 11156 HandleScope scope; |
| 11157 CONVERT_SMI_CHECKED(obj_id, args[0]); |
| 11158 Object* result = LiveObjectList::PrintObj(obj_id); |
| 11159 return result; |
| 11160 #else |
| 11161 return Heap::undefined_value(); |
| 11162 #endif |
| 11163 } |
| 11164 |
| 11165 |
| 11166 // Resets and releases all previously captured live object lists. |
| 11167 static MaybeObject* Runtime_ResetLOL(Arguments args) { |
| 11168 #ifdef LIVE_OBJECT_LIST |
| 11169 LiveObjectList::Reset(); |
| 11170 return Heap::undefined_value(); |
| 11171 #else |
| 11172 return Heap::undefined_value(); |
| 11173 #endif |
| 11174 } |
| 11175 |
| 11176 |
| 11177 // Generates the response to a debugger request for a summary of the types |
| 11178 // of objects in the difference between the captured live object lists |
| 11179 // specified by id1 and id2. |
| 11180 // If id1 is 0 (i.e. not a valid lol), then the whole of lol id2 will be |
| 11181 // summarized. |
| 11182 static MaybeObject* Runtime_SummarizeLOL(Arguments args) { |
| 11183 #ifdef LIVE_OBJECT_LIST |
| 11184 HandleScope scope; |
| 11185 CONVERT_SMI_CHECKED(id1, args[0]); |
| 11186 CONVERT_SMI_CHECKED(id2, args[1]); |
| 11187 CONVERT_ARG_CHECKED(JSObject, filter_obj, 2); |
| 11188 |
| 11189 EnterDebugger enter_debugger; |
| 11190 return LiveObjectList::Summarize(id1, id2, filter_obj); |
| 11191 #else |
| 11192 return Heap::undefined_value(); |
| 11193 #endif |
| 11194 } |
| 11195 |
| 10777 #endif // ENABLE_DEBUGGER_SUPPORT | 11196 #endif // ENABLE_DEBUGGER_SUPPORT |
| 10778 | 11197 |
| 10779 | 11198 |
| 10780 #ifdef ENABLE_LOGGING_AND_PROFILING | 11199 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 10781 static MaybeObject* Runtime_ProfilerResume(Arguments args) { | 11200 static MaybeObject* Runtime_ProfilerResume(Arguments args) { |
| 10782 NoHandleAllocation ha; | 11201 NoHandleAllocation ha; |
| 10783 ASSERT(args.length() == 2); | 11202 ASSERT(args.length() == 2); |
| 10784 | 11203 |
| 10785 CONVERT_CHECKED(Smi, smi_modules, args[0]); | 11204 CONVERT_CHECKED(Smi, smi_modules, args[0]); |
| 10786 CONVERT_CHECKED(Smi, smi_tag, args[1]); | 11205 CONVERT_CHECKED(Smi, smi_tag, args[1]); |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10883 // native code offset. | 11302 // native code offset. |
| 10884 static MaybeObject* Runtime_CollectStackTrace(Arguments args) { | 11303 static MaybeObject* Runtime_CollectStackTrace(Arguments args) { |
| 10885 ASSERT_EQ(args.length(), 2); | 11304 ASSERT_EQ(args.length(), 2); |
| 10886 Handle<Object> caller = args.at<Object>(0); | 11305 Handle<Object> caller = args.at<Object>(0); |
| 10887 CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]); | 11306 CONVERT_NUMBER_CHECKED(int32_t, limit, Int32, args[1]); |
| 10888 | 11307 |
| 10889 HandleScope scope; | 11308 HandleScope scope; |
| 10890 | 11309 |
| 10891 limit = Max(limit, 0); // Ensure that limit is not negative. | 11310 limit = Max(limit, 0); // Ensure that limit is not negative. |
| 10892 int initial_size = Min(limit, 10); | 11311 int initial_size = Min(limit, 10); |
| 10893 Handle<JSArray> result = Factory::NewJSArray(initial_size * 4); | 11312 Handle<FixedArray> elements = |
| 11313 Factory::NewFixedArrayWithHoles(initial_size * 4); |
| 10894 | 11314 |
| 10895 StackFrameIterator iter; | 11315 StackFrameIterator iter; |
| 10896 // If the caller parameter is a function we skip frames until we're | 11316 // If the caller parameter is a function we skip frames until we're |
| 10897 // under it before starting to collect. | 11317 // under it before starting to collect. |
| 10898 bool seen_caller = !caller->IsJSFunction(); | 11318 bool seen_caller = !caller->IsJSFunction(); |
| 10899 int cursor = 0; | 11319 int cursor = 0; |
| 10900 int frames_seen = 0; | 11320 int frames_seen = 0; |
| 10901 while (!iter.done() && frames_seen < limit) { | 11321 while (!iter.done() && frames_seen < limit) { |
| 10902 StackFrame* raw_frame = iter.frame(); | 11322 StackFrame* raw_frame = iter.frame(); |
| 10903 if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) { | 11323 if (ShowFrameInStackTrace(raw_frame, *caller, &seen_caller)) { |
| 10904 frames_seen++; | 11324 frames_seen++; |
| 10905 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); | 11325 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame); |
| 10906 List<FrameSummary> frames(3); // Max 2 levels of inlining. | 11326 List<FrameSummary> frames(3); // Max 2 levels of inlining. |
| 10907 frame->Summarize(&frames); | 11327 frame->Summarize(&frames); |
| 10908 for (int i = frames.length() - 1; i >= 0; i--) { | 11328 for (int i = frames.length() - 1; i >= 0; i--) { |
| 11329 if (cursor + 4 > elements->length()) { |
| 11330 int new_capacity = JSObject::NewElementsCapacity(elements->length()); |
| 11331 Handle<FixedArray> new_elements = |
| 11332 Factory::NewFixedArrayWithHoles(new_capacity); |
| 11333 for (int i = 0; i < cursor; i++) { |
| 11334 new_elements->set(i, elements->get(i)); |
| 11335 } |
| 11336 elements = new_elements; |
| 11337 } |
| 11338 ASSERT(cursor + 4 <= elements->length()); |
| 11339 |
| 10909 Handle<Object> recv = frames[i].receiver(); | 11340 Handle<Object> recv = frames[i].receiver(); |
| 10910 Handle<JSFunction> fun = frames[i].function(); | 11341 Handle<JSFunction> fun = frames[i].function(); |
| 10911 Handle<Code> code = frames[i].code(); | 11342 Handle<Code> code = frames[i].code(); |
| 10912 Handle<Smi> offset(Smi::FromInt(frames[i].offset())); | 11343 Handle<Smi> offset(Smi::FromInt(frames[i].offset())); |
| 10913 FixedArray* elements = FixedArray::cast(result->elements()); | 11344 elements->set(cursor++, *recv); |
| 10914 if (cursor + 3 < elements->length()) { | 11345 elements->set(cursor++, *fun); |
| 10915 elements->set(cursor++, *recv); | 11346 elements->set(cursor++, *code); |
| 10916 elements->set(cursor++, *fun); | 11347 elements->set(cursor++, *offset); |
| 10917 elements->set(cursor++, *code); | |
| 10918 elements->set(cursor++, *offset); | |
| 10919 } else { | |
| 10920 SetElement(result, cursor++, recv); | |
| 10921 SetElement(result, cursor++, fun); | |
| 10922 SetElement(result, cursor++, code); | |
| 10923 SetElement(result, cursor++, offset); | |
| 10924 } | |
| 10925 } | 11348 } |
| 10926 } | 11349 } |
| 10927 iter.Advance(); | 11350 iter.Advance(); |
| 10928 } | 11351 } |
| 10929 | 11352 Handle<JSArray> result = Factory::NewJSArrayWithElements(elements); |
| 10930 result->set_length(Smi::FromInt(cursor)); | 11353 result->set_length(Smi::FromInt(cursor)); |
| 10931 return *result; | 11354 return *result; |
| 10932 } | 11355 } |
| 10933 | 11356 |
| 10934 | 11357 |
| 10935 // Returns V8 version as a string. | 11358 // Returns V8 version as a string. |
| 10936 static MaybeObject* Runtime_GetV8Version(Arguments args) { | 11359 static MaybeObject* Runtime_GetV8Version(Arguments args) { |
| 10937 ASSERT_EQ(args.length(), 0); | 11360 ASSERT_EQ(args.length(), 0); |
| 10938 | 11361 |
| 10939 NoHandleAllocation ha; | 11362 NoHandleAllocation ha; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11084 return message->script(); | 11507 return message->script(); |
| 11085 } | 11508 } |
| 11086 | 11509 |
| 11087 | 11510 |
| 11088 #ifdef DEBUG | 11511 #ifdef DEBUG |
| 11089 // ListNatives is ONLY used by the fuzz-natives.js in debug mode | 11512 // ListNatives is ONLY used by the fuzz-natives.js in debug mode |
| 11090 // Exclude the code in release mode. | 11513 // Exclude the code in release mode. |
| 11091 static MaybeObject* Runtime_ListNatives(Arguments args) { | 11514 static MaybeObject* Runtime_ListNatives(Arguments args) { |
| 11092 ASSERT(args.length() == 0); | 11515 ASSERT(args.length() == 0); |
| 11093 HandleScope scope; | 11516 HandleScope scope; |
| 11094 Handle<JSArray> result = Factory::NewJSArray(0); | 11517 #define COUNT_ENTRY(Name, argc, ressize) + 1 |
| 11518 int entry_count = 0 |
| 11519 RUNTIME_FUNCTION_LIST(COUNT_ENTRY) |
| 11520 INLINE_FUNCTION_LIST(COUNT_ENTRY) |
| 11521 INLINE_RUNTIME_FUNCTION_LIST(COUNT_ENTRY); |
| 11522 #undef COUNT_ENTRY |
| 11523 Handle<FixedArray> elements = Factory::NewFixedArray(entry_count); |
| 11095 int index = 0; | 11524 int index = 0; |
| 11096 bool inline_runtime_functions = false; | 11525 bool inline_runtime_functions = false; |
| 11097 #define ADD_ENTRY(Name, argc, ressize) \ | 11526 #define ADD_ENTRY(Name, argc, ressize) \ |
| 11098 { \ | 11527 { \ |
| 11099 HandleScope inner; \ | 11528 HandleScope inner; \ |
| 11100 Handle<String> name; \ | 11529 Handle<String> name; \ |
| 11101 /* Inline runtime functions have an underscore in front of the name. */ \ | 11530 /* Inline runtime functions have an underscore in front of the name. */ \ |
| 11102 if (inline_runtime_functions) { \ | 11531 if (inline_runtime_functions) { \ |
| 11103 name = Factory::NewStringFromAscii( \ | 11532 name = Factory::NewStringFromAscii( \ |
| 11104 Vector<const char>("_" #Name, StrLength("_" #Name))); \ | 11533 Vector<const char>("_" #Name, StrLength("_" #Name))); \ |
| 11105 } else { \ | 11534 } else { \ |
| 11106 name = Factory::NewStringFromAscii( \ | 11535 name = Factory::NewStringFromAscii( \ |
| 11107 Vector<const char>(#Name, StrLength(#Name))); \ | 11536 Vector<const char>(#Name, StrLength(#Name))); \ |
| 11108 } \ | 11537 } \ |
| 11109 Handle<JSArray> pair = Factory::NewJSArray(0); \ | 11538 Handle<FixedArray> pair_elements = Factory::NewFixedArray(2); \ |
| 11110 SetElement(pair, 0, name); \ | 11539 pair_elements->set(0, *name); \ |
| 11111 SetElement(pair, 1, Handle<Smi>(Smi::FromInt(argc))); \ | 11540 pair_elements->set(1, Smi::FromInt(argc)); \ |
| 11112 SetElement(result, index++, pair); \ | 11541 Handle<JSArray> pair = Factory::NewJSArrayWithElements(pair_elements); \ |
| 11542 elements->set(index++, *pair); \ |
| 11113 } | 11543 } |
| 11114 inline_runtime_functions = false; | 11544 inline_runtime_functions = false; |
| 11115 RUNTIME_FUNCTION_LIST(ADD_ENTRY) | 11545 RUNTIME_FUNCTION_LIST(ADD_ENTRY) |
| 11116 inline_runtime_functions = true; | 11546 inline_runtime_functions = true; |
| 11117 INLINE_FUNCTION_LIST(ADD_ENTRY) | 11547 INLINE_FUNCTION_LIST(ADD_ENTRY) |
| 11118 INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY) | 11548 INLINE_RUNTIME_FUNCTION_LIST(ADD_ENTRY) |
| 11119 #undef ADD_ENTRY | 11549 #undef ADD_ENTRY |
| 11550 ASSERT_EQ(index, entry_count); |
| 11551 Handle<JSArray> result = Factory::NewJSArrayWithElements(elements); |
| 11120 return *result; | 11552 return *result; |
| 11121 } | 11553 } |
| 11122 #endif | 11554 #endif |
| 11123 | 11555 |
| 11124 | 11556 |
| 11125 static MaybeObject* Runtime_Log(Arguments args) { | 11557 static MaybeObject* Runtime_Log(Arguments args) { |
| 11126 ASSERT(args.length() == 2); | 11558 ASSERT(args.length() == 2); |
| 11127 CONVERT_CHECKED(String, format, args[0]); | 11559 CONVERT_CHECKED(String, format, args[0]); |
| 11128 CONVERT_CHECKED(JSArray, elms, args[1]); | 11560 CONVERT_CHECKED(JSArray, elms, args[1]); |
| 11129 Vector<const char> chars = format->ToAsciiVector(); | 11561 Vector<const char> chars = format->ToAsciiVector(); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11207 } else { | 11639 } else { |
| 11208 // Handle last resort GC and make sure to allow future allocations | 11640 // Handle last resort GC and make sure to allow future allocations |
| 11209 // to grow the heap without causing GCs (if possible). | 11641 // to grow the heap without causing GCs (if possible). |
| 11210 Counters::gc_last_resort_from_js.Increment(); | 11642 Counters::gc_last_resort_from_js.Increment(); |
| 11211 Heap::CollectAllGarbage(false); | 11643 Heap::CollectAllGarbage(false); |
| 11212 } | 11644 } |
| 11213 } | 11645 } |
| 11214 | 11646 |
| 11215 | 11647 |
| 11216 } } // namespace v8::internal | 11648 } } // namespace v8::internal |
| OLD | NEW |