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

Side by Side Diff: src/runtime.cc

Issue 40295: Optimizing generation of nested literals for both object and array literals. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 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') | test/mjsunit/fuzz-natives.js » ('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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 25 matching lines...) Expand all
36 #include "cpu.h" 36 #include "cpu.h"
37 #include "dateparser.h" 37 #include "dateparser.h"
38 #include "debug.h" 38 #include "debug.h"
39 #include "execution.h" 39 #include "execution.h"
40 #include "jsregexp.h" 40 #include "jsregexp.h"
41 #include "platform.h" 41 #include "platform.h"
42 #include "runtime.h" 42 #include "runtime.h"
43 #include "scopeinfo.h" 43 #include "scopeinfo.h"
44 #include "v8threads.h" 44 #include "v8threads.h"
45 #include "smart-pointer.h" 45 #include "smart-pointer.h"
46 #include "parser.h"
46 47
47 namespace v8 { namespace internal { 48 namespace v8 { namespace internal {
48 49
49 50
50 #define RUNTIME_ASSERT(value) do { \ 51 #define RUNTIME_ASSERT(value) do { \
51 if (!(value)) return IllegalOperation(); \ 52 if (!(value)) return IllegalOperation(); \
52 } while (false) 53 } while (false)
53 54
54 // Cast the given object to a value of the specified type and store 55 // Cast the given object to a value of the specified type and store
55 // it in a variable with the given name. If the object is not of the 56 // it in a variable with the given name. If the object is not of the
56 // expected type call IllegalOperation and return. 57 // expected type call IllegalOperation and return.
57 #define CONVERT_CHECKED(Type, name, obj) \ 58 #define CONVERT_CHECKED(Type, name, obj) \
58 RUNTIME_ASSERT(obj->Is##Type()); \ 59 RUNTIME_ASSERT(obj->Is##Type()); \
59 Type* name = Type::cast(obj); 60 Type* name = Type::cast(obj);
60 61
61 #define CONVERT_ARG_CHECKED(Type, name, index) \ 62 #define CONVERT_ARG_CHECKED(Type, name, index) \
62 RUNTIME_ASSERT(args[index]->Is##Type()); \ 63 RUNTIME_ASSERT(args[index]->Is##Type()); \
63 Handle<Type> name = args.at<Type>(index); 64 Handle<Type> name = args.at<Type>(index);
64 65
65 // Cast the given object to a boolean and store it in a variable with 66 // Cast the given object to a boolean and store it in a variable with
66 // the given name. If the object is not a boolean call IllegalOperation 67 // the given name. If the object is not a boolean call IllegalOperation
67 // and return. 68 // and return.
68 #define CONVERT_BOOLEAN_CHECKED(name, obj) \ 69 #define CONVERT_BOOLEAN_CHECKED(name, obj) \
69 RUNTIME_ASSERT(obj->IsBoolean()); \ 70 RUNTIME_ASSERT(obj->IsBoolean()); \
70 bool name = (obj)->IsTrue(); 71 bool name = (obj)->IsTrue();
71 72
73 // Cast the given object to an int and store it in a variable with
74 // the given name. If the object is not a Smi call IllegalOperation
75 // and return.
76 #define CONVERT_INT_CHECKED(name, obj) \
77 RUNTIME_ASSERT(obj->IsSmi()); \
78 int name = Smi::cast(obj)->value();
79
72 // Cast the given object to a double and store it in a variable with 80 // Cast the given object to a double and store it in a variable with
73 // the given name. If the object is not a number (as opposed to 81 // the given name. If the object is not a number (as opposed to
74 // the number not-a-number) call IllegalOperation and return. 82 // the number not-a-number) call IllegalOperation and return.
75 #define CONVERT_DOUBLE_CHECKED(name, obj) \ 83 #define CONVERT_DOUBLE_CHECKED(name, obj) \
76 RUNTIME_ASSERT(obj->IsNumber()); \ 84 RUNTIME_ASSERT(obj->IsNumber()); \
77 double name = (obj)->Number(); 85 double name = (obj)->Number();
78 86
79 // Call the specified converter on the object *comand store the result in 87 // Call the specified converter on the object *comand store the result in
80 // a variable of the specified type with the given name. If the 88 // a variable of the specified type with the given name. If the
81 // object is not a Number call IllegalOperation and return. 89 // object is not a Number call IllegalOperation and return.
82 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \ 90 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
83 RUNTIME_ASSERT(obj->IsNumber()); \ 91 RUNTIME_ASSERT(obj->IsNumber()); \
84 type name = NumberTo##Type(obj); 92 type name = NumberTo##Type(obj);
85 93
86 // Non-reentrant string buffer for efficient general use in this file. 94 // Non-reentrant string buffer for efficient general use in this file.
87 static StaticResource<StringInputBuffer> runtime_string_input_buffer; 95 static StaticResource<StringInputBuffer> runtime_string_input_buffer;
88 96
89 97
90 static Object* IllegalOperation() { 98 static Object* IllegalOperation() {
91 return Top::Throw(Heap::illegal_access_symbol()); 99 return Top::Throw(Heap::illegal_access_symbol());
92 } 100 }
93 101
94 102
95 static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) { 103 static Object* Runtime_CloneLiteralBoilerplate(Arguments args) {
96 CONVERT_CHECKED(JSObject, boilerplate, args[0]); 104 CONVERT_CHECKED(JSObject, boilerplate, args[0]);
97 return Heap::CopyJSObject(boilerplate); 105 return Heap::CopyJSObject(boilerplate);
98 } 106 }
99 107
100 108
101 static Handle<Map> ComputeObjectLiteralMap( 109 static Handle<Map> ComputeObjectLiteralMap(
102 Handle<Context> context, 110 Handle<Context> context,
103 Handle<FixedArray> constant_properties, 111 Handle<FixedArray> constant_properties,
104 bool* is_result_from_cache) { 112 bool* is_result_from_cache) {
105 int number_of_properties = constant_properties->length() / 2; 113 int number_of_properties = constant_properties->length() / 2;
(...skipping 18 matching lines...) Expand all
124 return Factory::ObjectLiteralMapFromCache(context, keys); 132 return Factory::ObjectLiteralMapFromCache(context, keys);
125 } 133 }
126 } 134 }
127 *is_result_from_cache = false; 135 *is_result_from_cache = false;
128 return Factory::CopyMap( 136 return Factory::CopyMap(
129 Handle<Map>(context->object_function()->initial_map()), 137 Handle<Map>(context->object_function()->initial_map()),
130 number_of_properties); 138 number_of_properties);
131 } 139 }
132 140
133 141
142 static Handle<Object> CreateLiteralBoilerplate(
143 Handle<FixedArray> literals,
144 Handle<FixedArray> constant_properties);
145
146
134 static Handle<Object> CreateObjectLiteralBoilerplate( 147 static Handle<Object> CreateObjectLiteralBoilerplate(
135 Handle<FixedArray> literals, 148 Handle<FixedArray> literals,
136 Handle<FixedArray> constant_properties) { 149 Handle<FixedArray> constant_properties) {
137 // Get the global context from the literals array. This is the 150 // Get the global context from the literals array. This is the
138 // context in which the function was created and we use the object 151 // context in which the function was created and we use the object
139 // function from this context to create the object literal. We do 152 // function from this context to create the object literal. We do
140 // not use the object function from the current global context 153 // not use the object function from the current global context
141 // because this might be the object function from another context 154 // because this might be the object function from another context
142 // which we should not have access to. 155 // which we should not have access to.
143 Handle<Context> context = 156 Handle<Context> context =
144 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals)); 157 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
145 158
146 bool is_result_from_cache; 159 bool is_result_from_cache;
147 Handle<Map> map = ComputeObjectLiteralMap(context, 160 Handle<Map> map = ComputeObjectLiteralMap(context,
148 constant_properties, 161 constant_properties,
149 &is_result_from_cache); 162 &is_result_from_cache);
150 163
151 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map); 164 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
152 { // Add the constant properties to the boilerplate. 165 { // Add the constant properties to the boilerplate.
153 int length = constant_properties->length(); 166 int length = constant_properties->length();
154 OptimizedObjectForAddingMultipleProperties opt(boilerplate, 167 OptimizedObjectForAddingMultipleProperties opt(boilerplate,
155 !is_result_from_cache); 168 !is_result_from_cache);
156 for (int index = 0; index < length; index +=2) { 169 for (int index = 0; index < length; index +=2) {
157 Handle<Object> key(constant_properties->get(index+0)); 170 Handle<Object> key(constant_properties->get(index+0));
158 Handle<Object> value(constant_properties->get(index+1)); 171 Handle<Object> value(constant_properties->get(index+1));
159 if (value->IsFixedArray()) { 172 if (value->IsFixedArray()) {
160 // The value contains the constant_properties of a 173 // The value contains the constant_properties of a
161 // simple object literal. 174 // simple object literal.
162 Handle<FixedArray> array = Handle<FixedArray>::cast(value); 175 Handle<FixedArray> array = Handle<FixedArray>::cast(value);
163 value = CreateObjectLiteralBoilerplate(literals, array); 176 value = CreateLiteralBoilerplate(literals, array);
177 if (value.is_null()) return value;
164 } 178 }
165 Handle<Object> result; 179 Handle<Object> result;
166 uint32_t element_index = 0; 180 uint32_t element_index = 0;
167 if (key->IsSymbol()) { 181 if (key->IsSymbol()) {
168 // If key is a symbol it is not an array element. 182 // If key is a symbol it is not an array element.
169 Handle<String> name(String::cast(*key)); 183 Handle<String> name(String::cast(*key));
170 ASSERT(!name->AsArrayIndex(&element_index)); 184 ASSERT(!name->AsArrayIndex(&element_index));
171 result = SetProperty(boilerplate, name, value, NONE); 185 result = SetProperty(boilerplate, name, value, NONE);
172 } else if (Array::IndexFromObject(*key, &element_index)) { 186 } else if (Array::IndexFromObject(*key, &element_index)) {
173 // Array index (uint32). 187 // Array index (uint32).
(...skipping 13 matching lines...) Expand all
187 // the handle based operations. In that case, we need to 201 // the handle based operations. In that case, we need to
188 // convert back to an exception. 202 // convert back to an exception.
189 if (result.is_null()) return result; 203 if (result.is_null()) return result;
190 } 204 }
191 } 205 }
192 206
193 return boilerplate; 207 return boilerplate;
194 } 208 }
195 209
196 210
211 static Handle<Object> CreateArrayLiteralBoilerplate(
212 Handle<FixedArray> literals,
213 Handle<FixedArray> elements) {
214 // Create the JSArray.
215 Handle<JSFunction> constructor(
216 JSFunction::GlobalContextFromLiterals(*literals)->array_function());
217 Handle<Object> object = Factory::NewJSObject(constructor);
218
219 Handle<Object> copied_elements = Factory::CopyFixedArray(elements);
220
221 Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
222 for (int i = 0; i < content->length(); i++) {
223 if (content->get(i)->IsFixedArray()) {
224 // The value contains the constant_properties of a
225 // simple object literal.
226 Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
227 Handle<Object> result = CreateLiteralBoilerplate(literals, fa);
228 if (result.is_null()) return result;
229 content->set(i, *result);
230 }
231 }
232
233 // Set the elements.
234 Handle<JSArray>::cast(object)->SetContent(*content);
235 return object;
236 }
237
238
239 static Handle<Object> CreateLiteralBoilerplate(
240 Handle<FixedArray> literals,
241 Handle<FixedArray> array) {
242 Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
243 switch (CompileTimeValue::GetType(array)) {
244 case CompileTimeValue::OBJECT_LITERAL:
245 return CreateObjectLiteralBoilerplate(literals, elements);
246 case CompileTimeValue::ARRAY_LITERAL:
247 return CreateArrayLiteralBoilerplate(literals, elements);
248 default:
249 UNREACHABLE();
250 return Handle<Object>::null();
251 }
252 }
253
254
197 static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) { 255 static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
198 HandleScope scope; 256 HandleScope scope;
199 ASSERT(args.length() == 3); 257 ASSERT(args.length() == 3);
200 // Copy the arguments. 258 // Copy the arguments.
201 Handle<FixedArray> literals = args.at<FixedArray>(0); 259 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
202 int literals_index = Smi::cast(args[1])->value(); 260 CONVERT_INT_CHECKED(literals_index, args[1]);
203 Handle<FixedArray> constant_properties = args.at<FixedArray>(2); 261 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
204 262
205 Handle<Object> result = 263 Handle<Object> result =
206 CreateObjectLiteralBoilerplate(literals, constant_properties); 264 CreateObjectLiteralBoilerplate(literals, constant_properties);
207 265
208 if (result.is_null()) return Failure::Exception(); 266 if (result.is_null()) return Failure::Exception();
209 267
210 // Update the functions literal and return the boilerplate. 268 // Update the functions literal and return the boilerplate.
211 literals->set(literals_index, *result); 269 literals->set(literals_index, *result);
212 270
213 return *result; 271 return *result;
214 } 272 }
215 273
216 274
217 static Object* Runtime_CreateArrayLiteral(Arguments args) { 275 static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
218 // Takes a FixedArray of elements containing the literal elements of 276 // Takes a FixedArray of elements containing the literal elements of
219 // the array literal and produces JSArray with those elements. 277 // the array literal and produces JSArray with those elements.
220 // Additionally takes the literals array of the surrounding function 278 // Additionally takes the literals array of the surrounding function
221 // which contains the context from which to get the Array function 279 // which contains the context from which to get the Array function
222 // to use for creating the array literal. 280 // to use for creating the array literal.
223 ASSERT(args.length() == 2); 281 HandleScope scope;
224 CONVERT_CHECKED(FixedArray, elements, args[0]); 282 ASSERT(args.length() == 3);
225 CONVERT_CHECKED(FixedArray, literals, args[1]); 283 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
226 JSFunction* constructor = 284 CONVERT_INT_CHECKED(literals_index, args[1]);
227 JSFunction::GlobalContextFromLiterals(literals)->array_function(); 285 CONVERT_ARG_CHECKED(FixedArray, elements, 2);
228 // Create the JSArray.
229 Object* object = Heap::AllocateJSObject(constructor);
230 if (object->IsFailure()) return object;
231 286
232 // Copy the elements. 287 Handle<Object> object = CreateArrayLiteralBoilerplate(literals, elements);
233 Object* content = elements->Copy(); 288 if (object.is_null()) return Failure::Exception();
234 if (content->IsFailure()) return content;
235 289
236 // Set the elements. 290 // Update the functions literal and return the boilerplate.
237 JSArray::cast(object)->SetContent(FixedArray::cast(content)); 291 literals->set(literals_index, *object);
238 return object; 292 return *object;
239 } 293 }
240 294
241 295
242 static Object* Runtime_CreateCatchExtensionObject(Arguments args) { 296 static Object* Runtime_CreateCatchExtensionObject(Arguments args) {
243 ASSERT(args.length() == 2); 297 ASSERT(args.length() == 2);
244 CONVERT_CHECKED(String, key, args[0]); 298 CONVERT_CHECKED(String, key, args[0]);
245 Object* value = args[1]; 299 Object* value = args[1];
246 // Create a catch context extension object. 300 // Create a catch context extension object.
247 JSFunction* constructor = 301 JSFunction* constructor =
248 Top::context()->global_context()->context_extension_function(); 302 Top::context()->global_context()->context_extension_function();
(...skipping 5883 matching lines...) Expand 10 before | Expand all | Expand 10 after
6132 } else { 6186 } else {
6133 // Handle last resort GC and make sure to allow future allocations 6187 // Handle last resort GC and make sure to allow future allocations
6134 // to grow the heap without causing GCs (if possible). 6188 // to grow the heap without causing GCs (if possible).
6135 Counters::gc_last_resort_from_js.Increment(); 6189 Counters::gc_last_resort_from_js.Increment();
6136 Heap::CollectAllGarbage(); 6190 Heap::CollectAllGarbage();
6137 } 6191 }
6138 } 6192 }
6139 6193
6140 6194
6141 } } // namespace v8::internal 6195 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | test/mjsunit/fuzz-natives.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698