| 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 | 
|---|