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

Side by Side Diff: src/runtime.cc

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime.h ('k') | src/runtime-profiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/runtime-profiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698