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 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 } | 92 } |
93 | 93 |
94 | 94 |
95 static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) { | 95 static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) { |
96 CONVERT_CHECKED(JSObject, boilerplate, args[0]); | 96 CONVERT_CHECKED(JSObject, boilerplate, args[0]); |
97 return Heap::CopyJSObject(boilerplate); | 97 return Heap::CopyJSObject(boilerplate); |
98 } | 98 } |
99 | 99 |
100 | 100 |
101 static Handle<Map> ComputeObjectLiteralMap( | 101 static Handle<Map> ComputeObjectLiteralMap( |
102 Handle<Context> context, | 102 Handle<Context> context, |
103 Handle<FixedArray> constant_properties, | 103 Handle<FixedArray> constant_properties, |
104 bool* is_result_from_cache) { | 104 bool* is_result_from_cache) { |
105 int number_of_properties = constant_properties->length() / 2; | 105 int number_of_properties = constant_properties->length() / 2; |
106 if (FLAG_canonicalize_object_literal_maps) { | 106 if (FLAG_canonicalize_object_literal_maps) { |
107 // First find prefix of consecutive symbol keys. | 107 // First find prefix of consecutive symbol keys. |
108 int number_of_symbol_keys = 0; | 108 int number_of_symbol_keys = 0; |
109 while ((number_of_symbol_keys < number_of_properties) && | 109 while ((number_of_symbol_keys < number_of_properties) && |
110 (constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) { | 110 (constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) { |
111 number_of_symbol_keys++; | 111 number_of_symbol_keys++; |
112 } | 112 } |
113 // Based on the number of prefix symbols key we decide whether | 113 // Based on the number of prefix symbols key we decide whether |
114 // to use the map cache in the global context. | 114 // to use the map cache in the global context. |
115 const int kMaxKeys = 10; | 115 const int kMaxKeys = 10; |
116 if ((number_of_symbol_keys == number_of_properties) && | 116 if ((number_of_symbol_keys == number_of_properties) && |
117 (number_of_symbol_keys < kMaxKeys)) { | 117 (number_of_symbol_keys < kMaxKeys)) { |
118 // Create the fixed array with the key. | 118 // Create the fixed array with the key. |
119 Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys); | 119 Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys); |
120 for (int i = 0; i < number_of_symbol_keys; i++) { | 120 for (int i = 0; i < number_of_symbol_keys; i++) { |
121 keys->set(i, constant_properties->get(i*2)); | 121 keys->set(i, constant_properties->get(i*2)); |
122 } | 122 } |
123 *is_result_from_cache = true; | 123 *is_result_from_cache = true; |
124 return Factory::ObjectLiteralMapFromCache(context, keys); | 124 return Factory::ObjectLiteralMapFromCache(context, keys); |
125 } | 125 } |
126 } | 126 } |
127 *is_result_from_cache = false; | 127 *is_result_from_cache = false; |
128 return Factory::CopyMap( | 128 return Factory::CopyMap( |
129 Handle<Map>(context->object_function()->initial_map()), | 129 Handle<Map>(context->object_function()->initial_map()), |
130 number_of_properties); | 130 number_of_properties); |
131 } | 131 } |
132 | 132 |
133 | 133 |
134 static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) { | 134 static Handle<Object> CreateObjectLiteralBoilerplate( |
135 HandleScope scope; | 135 Handle<FixedArray> literals, |
136 ASSERT(args.length() == 3); | 136 Handle<FixedArray> constant_properties) { |
137 // Copy the arguments. | |
138 Handle<FixedArray> literals = args.at<FixedArray>(0); | |
139 int literals_index = Smi::cast(args[1])->value(); | |
140 Handle<FixedArray> constant_properties = args.at<FixedArray>(2); | |
141 | |
142 // Get the global context from the literals array. This is the | 137 // Get the global context from the literals array. This is the |
143 // context in which the function was created and we use the object | 138 // context in which the function was created and we use the object |
144 // function from this context to create the object literal. We do | 139 // function from this context to create the object literal. We do |
145 // not use the object function from the current global context | 140 // not use the object function from the current global context |
146 // because this might be the object function from another context | 141 // because this might be the object function from another context |
147 // which we should not have access to. | 142 // which we should not have access to. |
148 Handle<Context> context = | 143 Handle<Context> context = |
149 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals)); | 144 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals)); |
150 | 145 |
151 bool is_result_from_cache; | 146 bool is_result_from_cache; |
152 Handle<Map> map = ComputeObjectLiteralMap(context, | 147 Handle<Map> map = ComputeObjectLiteralMap(context, |
153 constant_properties, | 148 constant_properties, |
154 &is_result_from_cache); | 149 &is_result_from_cache); |
155 | 150 |
156 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map); | 151 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map); |
157 { // Add the constant properties to the boilerplate. | 152 { // Add the constant properties to the boilerplate. |
158 int length = constant_properties->length(); | 153 int length = constant_properties->length(); |
159 OptimizedObjectForAddingMultipleProperties opt(boilerplate, | 154 OptimizedObjectForAddingMultipleProperties opt(boilerplate, |
160 !is_result_from_cache); | 155 !is_result_from_cache); |
161 for (int index = 0; index < length; index +=2) { | 156 for (int index = 0; index < length; index +=2) { |
162 Handle<Object> key(constant_properties->get(index+0)); | 157 Handle<Object> key(constant_properties->get(index+0)); |
163 Handle<Object> value(constant_properties->get(index+1)); | 158 Handle<Object> value(constant_properties->get(index+1)); |
| 159 if (value->IsFixedArray()) { |
| 160 // The value contains the constant_properties of a |
| 161 // simple object literal. |
| 162 Handle<FixedArray> array = Handle<FixedArray>::cast(value); |
| 163 value = CreateObjectLiteralBoilerplate(literals, array); |
| 164 } |
164 Handle<Object> result; | 165 Handle<Object> result; |
165 uint32_t element_index = 0; | 166 uint32_t element_index = 0; |
166 if (key->IsSymbol()) { | 167 if (key->IsSymbol()) { |
167 // If key is a symbol it is not an array element. | 168 // If key is a symbol it is not an array element. |
168 Handle<String> name(String::cast(*key)); | 169 Handle<String> name(String::cast(*key)); |
169 ASSERT(!name->AsArrayIndex(&element_index)); | 170 ASSERT(!name->AsArrayIndex(&element_index)); |
170 result = SetProperty(boilerplate, name, value, NONE); | 171 result = SetProperty(boilerplate, name, value, NONE); |
171 } else if (Array::IndexFromObject(*key, &element_index)) { | 172 } else if (Array::IndexFromObject(*key, &element_index)) { |
172 // Array index (uint32). | 173 // Array index (uint32). |
173 result = SetElement(boilerplate, element_index, value); | 174 result = SetElement(boilerplate, element_index, value); |
174 } else { | 175 } else { |
175 // Non-uint32 number. | 176 // Non-uint32 number. |
176 ASSERT(key->IsNumber()); | 177 ASSERT(key->IsNumber()); |
177 double num = key->Number(); | 178 double num = key->Number(); |
178 char arr[100]; | 179 char arr[100]; |
179 Vector<char> buffer(arr, ARRAY_SIZE(arr)); | 180 Vector<char> buffer(arr, ARRAY_SIZE(arr)); |
180 const char* str = DoubleToCString(num, buffer); | 181 const char* str = DoubleToCString(num, buffer); |
181 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); | 182 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); |
182 result = SetProperty(boilerplate, name, value, NONE); | 183 result = SetProperty(boilerplate, name, value, NONE); |
183 } | 184 } |
184 // If setting the property on the boilerplate throws an | 185 // If setting the property on the boilerplate throws an |
185 // exception, the exception is converted to an empty handle in | 186 // exception, the exception is converted to an empty handle in |
186 // the handle based operations. In that case, we need to | 187 // the handle based operations. In that case, we need to |
187 // convert back to an exception. | 188 // convert back to an exception. |
188 if (result.is_null()) return Failure::Exception(); | 189 if (result.is_null()) return result; |
189 } | 190 } |
190 } | 191 } |
191 | 192 |
192 // Update the functions literal and return the boilerplate. | 193 return boilerplate; |
193 literals->set(literals_index, *boilerplate); | |
194 | |
195 return *boilerplate; | |
196 } | 194 } |
197 | 195 |
198 | 196 |
| 197 static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) { |
| 198 HandleScope scope; |
| 199 ASSERT(args.length() == 3); |
| 200 // Copy the arguments. |
| 201 Handle<FixedArray> literals = args.at<FixedArray>(0); |
| 202 int literals_index = Smi::cast(args[1])->value(); |
| 203 Handle<FixedArray> constant_properties = args.at<FixedArray>(2); |
| 204 |
| 205 Handle<Object> result = |
| 206 CreateObjectLiteralBoilerplate(literals, constant_properties); |
| 207 |
| 208 if (result.is_null()) return Failure::Exception(); |
| 209 |
| 210 // Update the functions literal and return the boilerplate. |
| 211 literals->set(literals_index, *result);; |
| 212 |
| 213 return *result; |
| 214 } |
| 215 |
| 216 |
199 static Object* Runtime_CreateArrayLiteral(Arguments args) { | 217 static Object* Runtime_CreateArrayLiteral(Arguments args) { |
200 // Takes a FixedArray of elements containing the literal elements of | 218 // Takes a FixedArray of elements containing the literal elements of |
201 // the array literal and produces JSArray with those elements. | 219 // the array literal and produces JSArray with those elements. |
202 // Additionally takes the literals array of the surrounding function | 220 // Additionally takes the literals array of the surrounding function |
203 // which contains the context from which to get the Array function | 221 // which contains the context from which to get the Array function |
204 // to use for creating the array literal. | 222 // to use for creating the array literal. |
205 ASSERT(args.length() == 2); | 223 ASSERT(args.length() == 2); |
206 CONVERT_CHECKED(FixedArray, elements, args[0]); | 224 CONVERT_CHECKED(FixedArray, elements, args[0]); |
207 CONVERT_CHECKED(FixedArray, literals, args[1]); | 225 CONVERT_CHECKED(FixedArray, literals, args[1]); |
208 JSFunction* constructor = | 226 JSFunction* constructor = |
(...skipping 5909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6118 } else { | 6136 } else { |
6119 // Handle last resort GC and make sure to allow future allocations | 6137 // Handle last resort GC and make sure to allow future allocations |
6120 // to grow the heap without causing GCs (if possible). | 6138 // to grow the heap without causing GCs (if possible). |
6121 Counters::gc_last_resort_from_js.Increment(); | 6139 Counters::gc_last_resort_from_js.Increment(); |
6122 Heap::CollectAllGarbage(); | 6140 Heap::CollectAllGarbage(); |
6123 } | 6141 } |
6124 } | 6142 } |
6125 | 6143 |
6126 | 6144 |
6127 } } // namespace v8::internal | 6145 } } // namespace v8::internal |
OLD | NEW |