OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |