My favorites | Sign in
v8
Project Home Downloads Wiki Issues Source Code Search
Checkout   Browse   Changes  
Changes to /trunk/src/runtime.cc
r12661 vs. r12669 Compare: vs.  Format:
Revision r12669
Go to: 
Project members, sign in to write a code review
/trunk/src/runtime.cc   r12661 /trunk/src/runtime.cc   r12669
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <stdlib.h> 28 #include <stdlib.h>
29 29
30 #include "v8.h" 30 #include "v8.h"
31 31
32 #include "accessors.h" 32 #include "accessors.h"
33 #include "api.h" 33 #include "api.h"
34 #include "arguments.h" 34 #include "arguments.h"
35 #include "bootstrapper.h" 35 #include "bootstrapper.h"
36 #include "codegen.h" 36 #include "codegen.h"
37 #include "compilation-cache.h" 37 #include "compilation-cache.h"
38 #include "compiler.h" 38 #include "compiler.h"
39 #include "cpu.h" 39 #include "cpu.h"
40 #include "dateparser-inl.h" 40 #include "dateparser-inl.h"
41 #include "debug.h" 41 #include "debug.h"
42 #include "deoptimizer.h" 42 #include "deoptimizer.h"
43 #include "date.h" 43 #include "date.h"
44 #include "execution.h" 44 #include "execution.h"
45 #include "global-handles.h" 45 #include "global-handles.h"
46 #include "isolate-inl.h" 46 #include "isolate-inl.h"
47 #include "jsregexp.h" 47 #include "jsregexp.h"
48 #include "json-parser.h" 48 #include "json-parser.h"
49 #include "liveedit.h" 49 #include "liveedit.h"
50 #include "liveobjectlist-inl.h" 50 #include "liveobjectlist-inl.h"
51 #include "misc-intrinsics.h" 51 #include "misc-intrinsics.h"
52 #include "parser.h" 52 #include "parser.h"
53 #include "platform.h" 53 #include "platform.h"
54 #include "runtime-profiler.h" 54 #include "runtime-profiler.h"
55 #include "runtime.h" 55 #include "runtime.h"
56 #include "scopeinfo.h" 56 #include "scopeinfo.h"
57 #include "smart-pointers.h" 57 #include "smart-pointers.h"
58 #include "string-search.h" 58 #include "string-search.h"
59 #include "stub-cache.h" 59 #include "stub-cache.h"
60 #include "v8threads.h" 60 #include "v8threads.h"
61 #include "vm-state-inl.h" 61 #include "vm-state-inl.h"
62 62
63 namespace v8 { 63 namespace v8 {
64 namespace internal { 64 namespace internal {
65 65
66 66
67 #define RUNTIME_ASSERT(value) \ 67 #define RUNTIME_ASSERT(value) \
68 if (!(value)) return isolate->ThrowIllegalOperation(); 68 if (!(value)) return isolate->ThrowIllegalOperation();
69 69
70 // Cast the given object to a value of the specified type and store 70 // Cast the given object to a value of the specified type and store
71 // it in a variable with the given name. If the object is not of the 71 // it in a variable with the given name. If the object is not of the
72 // expected type call IllegalOperation and return. 72 // expected type call IllegalOperation and return.
73 #define CONVERT_ARG_CHECKED(Type, name, index) \ 73 #define CONVERT_ARG_CHECKED(Type, name, index) \
74 RUNTIME_ASSERT(args[index]->Is##Type()); \ 74 RUNTIME_ASSERT(args[index]->Is##Type()); \
75 Type* name = Type::cast(args[index]); 75 Type* name = Type::cast(args[index]);
76 76
77 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \ 77 #define CONVERT_ARG_HANDLE_CHECKED(Type, name, index) \
78 RUNTIME_ASSERT(args[index]->Is##Type()); \ 78 RUNTIME_ASSERT(args[index]->Is##Type()); \
79 Handle<Type> name = args.at<Type>(index); 79 Handle<Type> name = args.at<Type>(index);
80 80
81 // Cast the given object to a boolean and store it in a variable with 81 // Cast the given object to a boolean and store it in a variable with
82 // the given name. If the object is not a boolean call IllegalOperation 82 // the given name. If the object is not a boolean call IllegalOperation
83 // and return. 83 // and return.
84 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \ 84 #define CONVERT_BOOLEAN_ARG_CHECKED(name, index) \
85 RUNTIME_ASSERT(args[index]->IsBoolean()); \ 85 RUNTIME_ASSERT(args[index]->IsBoolean()); \
86 bool name = args[index]->IsTrue(); 86 bool name = args[index]->IsTrue();
87 87
88 // Cast the given argument to a Smi and store its value in an int variable 88 // Cast the given argument to a Smi and store its value in an int variable
89 // with the given name. If the argument is not a Smi call IllegalOperation 89 // with the given name. If the argument is not a Smi call IllegalOperation
90 // and return. 90 // and return.
91 #define CONVERT_SMI_ARG_CHECKED(name, index) \ 91 #define CONVERT_SMI_ARG_CHECKED(name, index) \
92 RUNTIME_ASSERT(args[index]->IsSmi()); \ 92 RUNTIME_ASSERT(args[index]->IsSmi()); \
93 int name = args.smi_at(index); 93 int name = args.smi_at(index);
94 94
95 // Cast the given argument to a double and store it in a variable with 95 // Cast the given argument to a double and store it in a variable with
96 // the given name. If the argument is not a number (as opposed to 96 // the given name. If the argument is not a number (as opposed to
97 // the number not-a-number) call IllegalOperation and return. 97 // the number not-a-number) call IllegalOperation and return.
98 #define CONVERT_DOUBLE_ARG_CHECKED(name, index) \ 98 #define CONVERT_DOUBLE_ARG_CHECKED(name, index) \
99 RUNTIME_ASSERT(args[index]->IsNumber()); \ 99 RUNTIME_ASSERT(args[index]->IsNumber()); \
100 double name = args.number_at(index); 100 double name = args.number_at(index);
101 101
102 // Call the specified converter on the object *comand store the result in 102 // Call the specified converter on the object *comand store the result in
103 // a variable of the specified type with the given name. If the 103 // a variable of the specified type with the given name. If the
104 // object is not a Number call IllegalOperation and return. 104 // object is not a Number call IllegalOperation and return.
105 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \ 105 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
106 RUNTIME_ASSERT(obj->IsNumber()); \ 106 RUNTIME_ASSERT(obj->IsNumber()); \
107 type name = NumberTo##Type(obj); 107 type name = NumberTo##Type(obj);
108 108
109 109
110 // Cast the given argument to PropertyDetails and store its value in a 110 // Cast the given argument to PropertyDetails and store its value in a
111 // variable with the given name. If the argument is not a Smi call 111 // variable with the given name. If the argument is not a Smi call
112 // IllegalOperation and return. 112 // IllegalOperation and return.
113 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \ 113 #define CONVERT_PROPERTY_DETAILS_CHECKED(name, index) \
114 RUNTIME_ASSERT(args[index]->IsSmi()); \ 114 RUNTIME_ASSERT(args[index]->IsSmi()); \
115 PropertyDetails name = PropertyDetails(Smi::cast(args[index])); 115 PropertyDetails name = PropertyDetails(Smi::cast(args[index]));
116 116
117 117
118 // Assert that the given argument has a valid value for a StrictModeFlag 118 // Assert that the given argument has a valid value for a StrictModeFlag
119 // and store it in a StrictModeFlag variable with the given name. 119 // and store it in a StrictModeFlag variable with the given name.
120 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index) \ 120 #define CONVERT_STRICT_MODE_ARG_CHECKED(name, index) \
121 RUNTIME_ASSERT(args[index]->IsSmi()); \ 121 RUNTIME_ASSERT(args[index]->IsSmi()); \
122 RUNTIME_ASSERT(args.smi_at(index) == kStrictMode || \ 122 RUNTIME_ASSERT(args.smi_at(index) == kStrictMode || \
123 args.smi_at(index) == kNonStrictMode); \ 123 args.smi_at(index) == kNonStrictMode); \
124 StrictModeFlag name = \ 124 StrictModeFlag name = \
125 static_cast<StrictModeFlag>(args.smi_at(index)); 125 static_cast<StrictModeFlag>(args.smi_at(index));
126 126
127 127
128 // Assert that the given argument has a valid value for a LanguageMode 128 // Assert that the given argument has a valid value for a LanguageMode
129 // and store it in a LanguageMode variable with the given name. 129 // and store it in a LanguageMode variable with the given name.
130 #define CONVERT_LANGUAGE_MODE_ARG(name, index) \ 130 #define CONVERT_LANGUAGE_MODE_ARG(name, index) \
131 ASSERT(args[index]->IsSmi()); \ 131 ASSERT(args[index]->IsSmi()); \
132 ASSERT(args.smi_at(index) == CLASSIC_MODE || \ 132 ASSERT(args.smi_at(index) == CLASSIC_MODE || \
133 args.smi_at(index) == STRICT_MODE || \ 133 args.smi_at(index) == STRICT_MODE || \
134 args.smi_at(index) == EXTENDED_MODE); \ 134 args.smi_at(index) == EXTENDED_MODE); \
135 LanguageMode name = \ 135 LanguageMode name = \
136 static_cast<LanguageMode>(args.smi_at(index)); 136 static_cast<LanguageMode>(args.smi_at(index));
137 137
138 138
139 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate, 139 MUST_USE_RESULT static MaybeObject* DeepCopyBoilerplate(Isolate* isolate,
140 JSObject* boilerplate) { 140 JSObject* boilerplate) {
141 StackLimitCheck check(isolate); 141 StackLimitCheck check(isolate);
142 if (check.HasOverflowed()) return isolate->StackOverflow(); 142 if (check.HasOverflowed()) return isolate->StackOverflow();
143 143
144 Heap* heap = isolate->heap(); 144 Heap* heap = isolate->heap();
145 Object* result; 145 Object* result;
146 { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate); 146 { MaybeObject* maybe_result = heap->CopyJSObject(boilerplate);
147 if (!maybe_result->ToObject(&result)) return maybe_result; 147 if (!maybe_result->ToObject(&result)) return maybe_result;
148 } 148 }
149 JSObject* copy = JSObject::cast(result); 149 JSObject* copy = JSObject::cast(result);
150 150
151 // Deep copy local properties. 151 // Deep copy local properties.
152 if (copy->HasFastProperties()) { 152 if (copy->HasFastProperties()) {
153 FixedArray* properties = copy->properties(); 153 FixedArray* properties = copy->properties();
154 for (int i = 0; i < properties->length(); i++) { 154 for (int i = 0; i < properties->length(); i++) {
155 Object* value = properties->get(i); 155 Object* value = properties->get(i);
156 if (value->IsJSObject()) { 156 if (value->IsJSObject()) {
157 JSObject* js_object = JSObject::cast(value); 157 JSObject* js_object = JSObject::cast(value);
158 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object); 158 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
159 if (!maybe_result->ToObject(&result)) return maybe_result; 159 if (!maybe_result->ToObject(&result)) return maybe_result;
160 } 160 }
161 properties->set(i, result); 161 properties->set(i, result);
162 } 162 }
163 } 163 }
164 int nof = copy->map()->inobject_properties(); 164 int nof = copy->map()->inobject_properties();
165 for (int i = 0; i < nof; i++) { 165 for (int i = 0; i < nof; i++) {
166 Object* value = copy->InObjectPropertyAt(i); 166 Object* value = copy->InObjectPropertyAt(i);
167 if (value->IsJSObject()) { 167 if (value->IsJSObject()) {
168 JSObject* js_object = JSObject::cast(value); 168 JSObject* js_object = JSObject::cast(value);
169 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object); 169 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
170 if (!maybe_result->ToObject(&result)) return maybe_result; 170 if (!maybe_result->ToObject(&result)) return maybe_result;
171 } 171 }
172 copy->InObjectPropertyAtPut(i, result); 172 copy->InObjectPropertyAtPut(i, result);
173 } 173 }
174 } 174 }
175 } else { 175 } else {
176 { MaybeObject* maybe_result = 176 { MaybeObject* maybe_result =
177 heap->AllocateFixedArray(copy->NumberOfLocalProperties()); 177 heap->AllocateFixedArray(copy->NumberOfLocalProperties());
178 if (!maybe_result->ToObject(&result)) return maybe_result; 178 if (!maybe_result->ToObject(&result)) return maybe_result;
179 } 179 }
180 FixedArray* names = FixedArray::cast(result); 180 FixedArray* names = FixedArray::cast(result);
181 copy->GetLocalPropertyNames(names, 0); 181 copy->GetLocalPropertyNames(names, 0);
182 for (int i = 0; i < names->length(); i++) { 182 for (int i = 0; i < names->length(); i++) {
183 ASSERT(names->get(i)->IsString()); 183 ASSERT(names->get(i)->IsString());
184 String* key_string = String::cast(names->get(i)); 184 String* key_string = String::cast(names->get(i));
185 PropertyAttributes attributes = 185 PropertyAttributes attributes =
186 copy->GetLocalPropertyAttribute(key_string); 186 copy->GetLocalPropertyAttribute(key_string);
187 // Only deep copy fields from the object literal expression. 187 // Only deep copy fields from the object literal expression.
188 // In particular, don't try to copy the length attribute of 188 // In particular, don't try to copy the length attribute of
189 // an array. 189 // an array.
190 if (attributes != NONE) continue; 190 if (attributes != NONE) continue;
191 Object* value = 191 Object* value =
192 copy->GetProperty(key_string, &attributes)->ToObjectUnchecked(); 192 copy->GetProperty(key_string, &attributes)->ToObjectUnchecked();
193 if (value->IsJSObject()) { 193 if (value->IsJSObject()) {
194 JSObject* js_object = JSObject::cast(value); 194 JSObject* js_object = JSObject::cast(value);
195 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object); 195 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, js_object);
196 if (!maybe_result->ToObject(&result)) return maybe_result; 196 if (!maybe_result->ToObject(&result)) return maybe_result;
197 } 197 }
198 { MaybeObject* maybe_result = 198 { MaybeObject* maybe_result =
199 // Creating object copy for literals. No strict mode needed. 199 // Creating object copy for literals. No strict mode needed.
200 copy->SetProperty(key_string, result, NONE, kNonStrictMode); 200 copy->SetProperty(key_string, result, NONE, kNonStrictMode);
201 if (!maybe_result->ToObject(&result)) return maybe_result; 201 if (!maybe_result->ToObject(&result)) return maybe_result;
202 } 202 }
203 } 203 }
204 } 204 }
205 } 205 }
206 206
207 // Deep copy local elements. 207 // Deep copy local elements.
208 // Pixel elements cannot be created using an object literal. 208 // Pixel elements cannot be created using an object literal.
209 ASSERT(!copy->HasExternalArrayElements()); 209 ASSERT(!copy->HasExternalArrayElements());
210 switch (copy->GetElementsKind()) { 210 switch (copy->GetElementsKind()) {
211 case FAST_SMI_ELEMENTS: 211 case FAST_SMI_ELEMENTS:
212 case FAST_ELEMENTS: 212 case FAST_ELEMENTS:
213 case FAST_HOLEY_SMI_ELEMENTS: 213 case FAST_HOLEY_SMI_ELEMENTS:
214 case FAST_HOLEY_ELEMENTS: { 214 case FAST_HOLEY_ELEMENTS: {
215 FixedArray* elements = FixedArray::cast(copy->elements()); 215 FixedArray* elements = FixedArray::cast(copy->elements());
216 if (elements->map() == heap->fixed_cow_array_map()) { 216 if (elements->map() == heap->fixed_cow_array_map()) {
217 isolate->counters()->cow_arrays_created_runtime()->Increment(); 217 isolate->counters()->cow_arrays_created_runtime()->Increment();
218 #ifdef DEBUG 218 #ifdef DEBUG
219 for (int i = 0; i < elements->length(); i++) { 219 for (int i = 0; i < elements->length(); i++) {
220 ASSERT(!elements->get(i)->IsJSObject()); 220 ASSERT(!elements->get(i)->IsJSObject());
221 } 221 }
222 #endif 222 #endif
223 } else { 223 } else {
224 for (int i = 0; i < elements->length(); i++) { 224 for (int i = 0; i < elements->length(); i++) {
225 Object* value = elements->get(i); 225 Object* value = elements->get(i);
226 ASSERT(value->IsSmi() || 226 ASSERT(value->IsSmi() ||
227 value->IsTheHole() || 227 value->IsTheHole() ||
228 (IsFastObjectElementsKind(copy->GetElementsKind()))); 228 (IsFastObjectElementsKind(copy->GetElementsKind())));
229 if (value->IsJSObject()) { 229 if (value->IsJSObject()) {
230 JSObject* js_object = JSObject::cast(value); 230 JSObject* js_object = JSObject::cast(value);
231 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, 231 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
232 js_object); 232 js_object);
233 if (!maybe_result->ToObject(&result)) return maybe_result; 233 if (!maybe_result->ToObject(&result)) return maybe_result;
234 } 234 }
235 elements->set(i, result); 235 elements->set(i, result);
236 } 236 }
237 } 237 }
238 } 238 }
239 break; 239 break;
240 } 240 }
241 case DICTIONARY_ELEMENTS: { 241 case DICTIONARY_ELEMENTS: {
242 SeededNumberDictionary* element_dictionary = copy->element_dictionary(); 242 SeededNumberDictionary* element_dictionary = copy->element_dictionary();
243 int capacity = element_dictionary->Capacity(); 243 int capacity = element_dictionary->Capacity();
244 for (int i = 0; i < capacity; i++) { 244 for (int i = 0; i < capacity; i++) {
245 Object* k = element_dictionary->KeyAt(i); 245 Object* k = element_dictionary->KeyAt(i);
246 if (element_dictionary->IsKey(k)) { 246 if (element_dictionary->IsKey(k)) {
247 Object* value = element_dictionary->ValueAt(i); 247 Object* value = element_dictionary->ValueAt(i);
248 if (value->IsJSObject()) { 248 if (value->IsJSObject()) {
249 JSObject* js_object = JSObject::cast(value); 249 JSObject* js_object = JSObject::cast(value);
250 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate, 250 { MaybeObject* maybe_result = DeepCopyBoilerplate(isolate,
251 js_object); 251 js_object);
252 if (!maybe_result->ToObject(&result)) return maybe_result; 252 if (!maybe_result->ToObject(&result)) return maybe_result;
253 } 253 }
254 element_dictionary->ValueAtPut(i, result); 254 element_dictionary->ValueAtPut(i, result);
255 } 255 }
256 } 256 }
257 } 257 }
258 break; 258 break;
259 } 259 }
260 case NON_STRICT_ARGUMENTS_ELEMENTS: 260 case NON_STRICT_ARGUMENTS_ELEMENTS:
261 UNIMPLEMENTED(); 261 UNIMPLEMENTED();
262 break; 262 break;
263 case EXTERNAL_PIXEL_ELEMENTS: 263 case EXTERNAL_PIXEL_ELEMENTS:
264 case EXTERNAL_BYTE_ELEMENTS: 264 case EXTERNAL_BYTE_ELEMENTS:
265 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 265 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
266 case EXTERNAL_SHORT_ELEMENTS: 266 case EXTERNAL_SHORT_ELEMENTS:
267 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 267 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
268 case EXTERNAL_INT_ELEMENTS: 268 case EXTERNAL_INT_ELEMENTS:
269 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 269 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
270 case EXTERNAL_FLOAT_ELEMENTS: 270 case EXTERNAL_FLOAT_ELEMENTS:
271 case EXTERNAL_DOUBLE_ELEMENTS: 271 case EXTERNAL_DOUBLE_ELEMENTS:
272 case FAST_DOUBLE_ELEMENTS: 272 case FAST_DOUBLE_ELEMENTS:
273 case FAST_HOLEY_DOUBLE_ELEMENTS: 273 case FAST_HOLEY_DOUBLE_ELEMENTS:
274 // No contained objects, nothing to do. 274 // No contained objects, nothing to do.
275 break; 275 break;
276 } 276 }
277 return copy; 277 return copy;
278 } 278 }
279 279
280 280
281 static Handle<Map> ComputeObjectLiteralMap( 281 static Handle<Map> ComputeObjectLiteralMap(
282 Handle<Context> context, 282 Handle<Context> context,
283 Handle<FixedArray> constant_properties, 283 Handle<FixedArray> constant_properties,
284 bool* is_result_from_cache) { 284 bool* is_result_from_cache) {
285 Isolate* isolate = context->GetIsolate(); 285 Isolate* isolate = context->GetIsolate();
286 int properties_length = constant_properties->length(); 286 int properties_length = constant_properties->length();
287 int number_of_properties = properties_length / 2; 287 int number_of_properties = properties_length / 2;
288 // Check that there are only symbols and array indices among keys. 288 // Check that there are only symbols and array indices among keys.
289 int number_of_symbol_keys = 0; 289 int number_of_symbol_keys = 0;
290 for (int p = 0; p != properties_length; p += 2) { 290 for (int p = 0; p != properties_length; p += 2) {
291 Object* key = constant_properties->get(p); 291 Object* key = constant_properties->get(p);
292 uint32_t element_index = 0; 292 uint32_t element_index = 0;
293 if (key->IsSymbol()) { 293 if (key->IsSymbol()) {
294 number_of_symbol_keys++; 294 number_of_symbol_keys++;
295 } else if (key->ToArrayIndex(&element_index)) { 295 } else if (key->ToArrayIndex(&element_index)) {
296 // An index key does not require space in the property backing store. 296 // An index key does not require space in the property backing store.
297 number_of_properties--; 297 number_of_properties--;
298 } else { 298 } else {
299 // Bail out as a non-symbol non-index key makes caching impossible. 299 // Bail out as a non-symbol non-index key makes caching impossible.
300 // ASSERT to make sure that the if condition after the loop is false. 300 // ASSERT to make sure that the if condition after the loop is false.
301 ASSERT(number_of_symbol_keys != number_of_properties); 301 ASSERT(number_of_symbol_keys != number_of_properties);
302 break; 302 break;
303 } 303 }
304 } 304 }
305 // If we only have symbols and array indices among keys then we can 305 // If we only have symbols and array indices among keys then we can
306 // use the map cache in the native context. 306 // use the map cache in the native context.
307 const int kMaxKeys = 10; 307 const int kMaxKeys = 10;
308 if ((number_of_symbol_keys == number_of_properties) && 308 if ((number_of_symbol_keys == number_of_properties) &&
309 (number_of_symbol_keys < kMaxKeys)) { 309 (number_of_symbol_keys < kMaxKeys)) {
310 // Create the fixed array with the key. 310 // Create the fixed array with the key.
311 Handle<FixedArray> keys = 311 Handle<FixedArray> keys =
312 isolate->factory()->NewFixedArray(number_of_symbol_keys); 312 isolate->factory()->NewFixedArray(number_of_symbol_keys);
313 if (number_of_symbol_keys > 0) { 313 if (number_of_symbol_keys > 0) {
314 int index = 0; 314 int index = 0;
315 for (int p = 0; p < properties_length; p += 2) { 315 for (int p = 0; p < properties_length; p += 2) {
316 Object* key = constant_properties->get(p); 316 Object* key = constant_properties->get(p);
317 if (key->IsSymbol()) { 317 if (key->IsSymbol()) {
318 keys->set(index++, key); 318 keys->set(index++, key);
319 } 319 }
320 } 320 }
321 ASSERT(index == number_of_symbol_keys); 321 ASSERT(index == number_of_symbol_keys);
322 } 322 }
323 *is_result_from_cache = true; 323 *is_result_from_cache = true;
324 return isolate->factory()->ObjectLiteralMapFromCache(context, keys); 324 return isolate->factory()->ObjectLiteralMapFromCache(context, keys);
325 } 325 }
326 *is_result_from_cache = false; 326 *is_result_from_cache = false;
327 return isolate->factory()->CopyMap( 327 return isolate->factory()->CopyMap(
328 Handle<Map>(context->object_function()->initial_map()), 328 Handle<Map>(context->object_function()->initial_map()),
329 number_of_properties); 329 number_of_properties);
330 } 330 }
331 331
332 332
333 static Handle<Object> CreateLiteralBoilerplate( 333 static Handle<Object> CreateLiteralBoilerplate(
334 Isolate* isolate, 334 Isolate* isolate,
335 Handle<FixedArray> literals, 335 Handle<FixedArray> literals,
336 Handle<FixedArray> constant_properties); 336 Handle<FixedArray> constant_properties);
337 337
338 338
339 static Handle<Object> CreateObjectLiteralBoilerplate( 339 static Handle<Object> CreateObjectLiteralBoilerplate(
340 Isolate* isolate, 340 Isolate* isolate,
341 Handle<FixedArray> literals, 341 Handle<FixedArray> literals,
342 Handle<FixedArray> constant_properties, 342 Handle<FixedArray> constant_properties,
343 bool should_have_fast_elements, 343 bool should_have_fast_elements,
344 bool has_function_literal) { 344 bool has_function_literal) {
345 // Get the native context from the literals array. This is the 345 // Get the native context from the literals array. This is the
346 // context in which the function was created and we use the object 346 // context in which the function was created and we use the object
347 // function from this context to create the object literal. We do 347 // function from this context to create the object literal. We do
348 // not use the object function from the current native context 348 // not use the object function from the current native context
349 // because this might be the object function from another context 349 // because this might be the object function from another context
350 // which we should not have access to. 350 // which we should not have access to.
351 Handle<Context> context = 351 Handle<Context> context =
352 Handle<Context>(JSFunction::NativeContextFromLiterals(*literals)); 352 Handle<Context>(JSFunction::NativeContextFromLiterals(*literals));
353 353
354 // In case we have function literals, we want the object to be in 354 // In case we have function literals, we want the object to be in
355 // slow properties mode for now. We don't go in the map cache because 355 // slow properties mode for now. We don't go in the map cache because
356 // maps with constant functions can't be shared if the functions are 356 // maps with constant functions can't be shared if the functions are
357 // not the same (which is the common case). 357 // not the same (which is the common case).
358 bool is_result_from_cache = false; 358 bool is_result_from_cache = false;
359 Handle<Map> map = has_function_literal 359 Handle<Map> map = has_function_literal
360 ? Handle<Map>(context->object_function()->initial_map()) 360 ? Handle<Map>(context->object_function()->initial_map())
361 : ComputeObjectLiteralMap(context, 361 : ComputeObjectLiteralMap(context,
362 constant_properties, 362 constant_properties,
363 &is_result_from_cache); 363 &is_result_from_cache);
364 364
365 Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map); 365 Handle<JSObject> boilerplate = isolate->factory()->NewJSObjectFromMap(map);
366 366
367 // Normalize the elements of the boilerplate to save space if needed. 367 // Normalize the elements of the boilerplate to save space if needed.
368 if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate); 368 if (!should_have_fast_elements) JSObject::NormalizeElements(boilerplate);
369 369
370 // Add the constant properties to the boilerplate. 370 // Add the constant properties to the boilerplate.
371 int length = constant_properties->length(); 371 int length = constant_properties->length();
372 bool should_transform = 372 bool should_transform =
373 !is_result_from_cache && boilerplate->HasFastProperties(); 373 !is_result_from_cache && boilerplate->HasFastProperties();
374 if (should_transform || has_function_literal) { 374 if (should_transform || has_function_literal) {
375 // Normalize the properties of object to avoid n^2 behavior 375 // Normalize the properties of object to avoid n^2 behavior
376 // when extending the object multiple properties. Indicate the number of 376 // when extending the object multiple properties. Indicate the number of
377 // properties to be added. 377 // properties to be added.
378 JSObject::NormalizeProperties( 378 JSObject::NormalizeProperties(
379 boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2); 379 boilerplate, KEEP_INOBJECT_PROPERTIES, length / 2);
380 } 380 }
381 381
382 for (int index = 0; index < length; index +=2) { 382 for (int index = 0; index < length; index +=2) {
383 Handle<Object> key(constant_properties->get(index+0), isolate); 383 Handle<Object> key(constant_properties->get(index+0), isolate);
384 Handle<Object> value(constant_properties->get(index+1), isolate); 384 Handle<Object> value(constant_properties->get(index+1), isolate);
385 if (value->IsFixedArray()) { 385 if (value->IsFixedArray()) {
386 // The value contains the constant_properties of a 386 // The value contains the constant_properties of a
387 // simple object or array literal. 387 // simple object or array literal.
388 Handle<FixedArray> array = Handle<FixedArray>::cast(value); 388 Handle<FixedArray> array = Handle<FixedArray>::cast(value);
389 value = CreateLiteralBoilerplate(isolate, literals, array); 389 value = CreateLiteralBoilerplate(isolate, literals, array);
390 if (value.is_null()) return value; 390 if (value.is_null()) return value;
391 } 391 }
392 Handle<Object> result; 392 Handle<Object> result;
393 uint32_t element_index = 0; 393 uint32_t element_index = 0;
394 if (key->IsSymbol()) { 394 if (key->IsSymbol()) {
395 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) { 395 if (Handle<String>::cast(key)->AsArrayIndex(&element_index)) {
396 // Array index as string (uint32). 396 // Array index as string (uint32).
397 result = JSObject::SetOwnElement( 397 result = JSObject::SetOwnElement(
398 boilerplate, element_index, value, kNonStrictMode); 398 boilerplate, element_index, value, kNonStrictMode);
399 } else { 399 } else {
400 Handle<String> name(String::cast(*key)); 400 Handle<String> name(String::cast(*key));
401 ASSERT(!name->AsArrayIndex(&element_index)); 401 ASSERT(!name->AsArrayIndex(&element_index));
402 result = JSObject::SetLocalPropertyIgnoreAttributes( 402 result = JSObject::SetLocalPropertyIgnoreAttributes(
403 boilerplate, name, value, NONE); 403 boilerplate, name, value, NONE);
404 } 404 }
405 } else if (key->ToArrayIndex(&element_index)) { 405 } else if (key->ToArrayIndex(&element_index)) {
406 // Array index (uint32). 406 // Array index (uint32).
407 result = JSObject::SetOwnElement( 407 result = JSObject::SetOwnElement(
408 boilerplate, element_index, value, kNonStrictMode); 408 boilerplate, element_index, value, kNonStrictMode);
409 } else { 409 } else {
410 // Non-uint32 number. 410 // Non-uint32 number.
411 ASSERT(key->IsNumber()); 411 ASSERT(key->IsNumber());
412 double num = key->Number(); 412 double num = key->Number();
413 char arr[100]; 413 char arr[100];
414 Vector<char> buffer(arr, ARRAY_SIZE(arr)); 414 Vector<char> buffer(arr, ARRAY_SIZE(arr));
415 const char* str = DoubleToCString(num, buffer); 415 const char* str = DoubleToCString(num, buffer);
416 Handle<String> name = 416 Handle<String> name =
417 isolate->factory()->NewStringFromAscii(CStrVector(str)); 417 isolate->factory()->NewStringFromAscii(CStrVector(str));
418 result = JSObject::SetLocalPropertyIgnoreAttributes( 418 result = JSObject::SetLocalPropertyIgnoreAttributes(
419 boilerplate, name, value, NONE); 419 boilerplate, name, value, NONE);
420 } 420 }
421 // If setting the property on the boilerplate throws an 421 // If setting the property on the boilerplate throws an
422 // exception, the exception is converted to an empty handle in 422 // exception, the exception is converted to an empty handle in
423 // the handle based operations. In that case, we need to 423 // the handle based operations. In that case, we need to
424 // convert back to an exception. 424 // convert back to an exception.
425 if (result.is_null()) return result; 425 if (result.is_null()) return result;
426 } 426 }
427 427
428 // Transform to fast properties if necessary. For object literals with 428 // Transform to fast properties if necessary. For object literals with
429 // containing function literals we defer this operation until after all 429 // containing function literals we defer this operation until after all
430 // computed properties have been assigned so that we can generate 430 // computed properties have been assigned so that we can generate
431 // constant function properties. 431 // constant function properties.
432 if (should_transform && !has_function_literal) { 432 if (should_transform && !has_function_literal) {
433 JSObject::TransformToFastProperties( 433 JSObject::TransformToFastProperties(
434 boilerplate, boilerplate->map()->unused_property_fields()); 434 boilerplate, boilerplate->map()->unused_property_fields());
435 } 435 }
436 436
437 return boilerplate; 437 return boilerplate;
438 } 438 }
439 439
440 440
441 MaybeObject* TransitionElements(Handle<Object> object, 441 MaybeObject* TransitionElements(Handle<Object> object,
442 ElementsKind to_kind, 442 ElementsKind to_kind,
443 Isolate* isolate) { 443 Isolate* isolate) {
444 HandleScope scope(isolate); 444 HandleScope scope(isolate);
445 if (!object->IsJSObject()) return isolate->ThrowIllegalOperation(); 445 if (!object->IsJSObject()) return isolate->ThrowIllegalOperation();
446 ElementsKind from_kind = 446 ElementsKind from_kind =
447 Handle<JSObject>::cast(object)->map()->elements_kind(); 447 Handle<JSObject>::cast(object)->map()->elements_kind();
448 if (Map::IsValidElementsTransition(from_kind, to_kind)) { 448 if (Map::IsValidElementsTransition(from_kind, to_kind)) {
449 Handle<Object> result = JSObject::TransitionElementsKind( 449 Handle<Object> result = JSObject::TransitionElementsKind(
450 Handle<JSObject>::cast(object), to_kind); 450 Handle<JSObject>::cast(object), to_kind);
451 if (result.is_null()) return isolate->ThrowIllegalOperation(); 451 if (result.is_null()) return isolate->ThrowIllegalOperation();
452 return *result; 452 return *result;
453 } 453 }
454 return isolate->ThrowIllegalOperation(); 454 return isolate->ThrowIllegalOperation();
455 } 455 }
456 456
457 457
458 static const int kSmiLiteralMinimumLength = 1024; 458 static const int kSmiLiteralMinimumLength = 1024;
459 459
460 460
461 Handle<Object> Runtime::CreateArrayLiteralBoilerplate( 461 Handle<Object> Runtime::CreateArrayLiteralBoilerplate(
462 Isolate* isolate, 462 Isolate* isolate,
463 Handle<FixedArray> literals, 463 Handle<FixedArray> literals,
464 Handle<FixedArray> elements) { 464 Handle<FixedArray> elements) {
465 // Create the JSArray. 465 // Create the JSArray.
466 Handle<JSFunction> constructor( 466 Handle<JSFunction> constructor(
467 JSFunction::NativeContextFromLiterals(*literals)->array_function()); 467 JSFunction::NativeContextFromLiterals(*literals)->array_function());
468 Handle<JSArray> object = 468 Handle<JSArray> object =
469 Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor)); 469 Handle<JSArray>::cast(isolate->factory()->NewJSObject(constructor));
470 470
471 ElementsKind constant_elements_kind = 471 ElementsKind constant_elements_kind =
472 static_cast<ElementsKind>(Smi::cast(elements->get(0))->value()); 472 static_cast<ElementsKind>(Smi::cast(elements->get(0))->value());
473 Handle<FixedArrayBase> constant_elements_values( 473 Handle<FixedArrayBase> constant_elements_values(
474 FixedArrayBase::cast(elements->get(1))); 474 FixedArrayBase::cast(elements->get(1)));
475 475
476 ASSERT(IsFastElementsKind(constant_elements_kind)); 476 ASSERT(IsFastElementsKind(constant_elements_kind));
477 Context* native_context = isolate->context()->native_context(); 477 Context* native_context = isolate->context()->native_context();
478 Object* maybe_maps_array = native_context->js_array_maps(); 478 Object* maybe_maps_array = native_context->js_array_maps();
479 ASSERT(!maybe_maps_array->IsUndefined()); 479 ASSERT(!maybe_maps_array->IsUndefined());
480 Object* maybe_map = FixedArray::cast(maybe_maps_array)->get( 480 Object* maybe_map = FixedArray::cast(maybe_maps_array)->get(
481 constant_elements_kind); 481 constant_elements_kind);
482 ASSERT(maybe_map->IsMap()); 482 ASSERT(maybe_map->IsMap());
483 object->set_map(Map::cast(maybe_map)); 483 object->set_map(Map::cast(maybe_map));
484 484
485 Handle<FixedArrayBase> copied_elements_values; 485 Handle<FixedArrayBase> copied_elements_values;
486 if (IsFastDoubleElementsKind(constant_elements_kind)) { 486 if (IsFastDoubleElementsKind(constant_elements_kind)) {
487 ASSERT(FLAG_smi_only_arrays); 487 ASSERT(FLAG_smi_only_arrays);
488 copied_elements_values = isolate->factory()->CopyFixedDoubleArray( 488 copied_elements_values = isolate->factory()->CopyFixedDoubleArray(
489 Handle<FixedDoubleArray>::cast(constant_elements_values)); 489 Handle<FixedDoubleArray>::cast(constant_elements_values));
490 } else { 490 } else {
491 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind)); 491 ASSERT(IsFastSmiOrObjectElementsKind(constant_elements_kind));
492 const bool is_cow = 492 const bool is_cow =
493 (constant_elements_values->map() == 493 (constant_elements_values->map() ==
494 isolate->heap()->fixed_cow_array_map()); 494 isolate->heap()->fixed_cow_array_map());
495 if (is_cow) { 495 if (is_cow) {
496 copied_elements_values = constant_elements_values; 496 copied_elements_values = constant_elements_values;
497 #if DEBUG 497 #if DEBUG
498 Handle<FixedArray> fixed_array_values = 498 Handle<FixedArray> fixed_array_values =
499 Handle<FixedArray>::cast(copied_elements_values); 499 Handle<FixedArray>::cast(copied_elements_values);
500 for (int i = 0; i < fixed_array_values->length(); i++) { 500 for (int i = 0; i < fixed_array_values->length(); i++) {
501 ASSERT(!fixed_array_values->get(i)->IsFixedArray()); 501 ASSERT(!fixed_array_values->get(i)->IsFixedArray());
502 } 502 }
503 #endif 503 #endif
504 } else { 504 } else {
505 Handle<FixedArray> fixed_array_values = 505 Handle<FixedArray> fixed_array_values =
506 Handle<FixedArray>::cast(constant_elements_values); 506 Handle<FixedArray>::cast(constant_elements_values);
507 Handle<FixedArray> fixed_array_values_copy = 507 Handle<FixedArray> fixed_array_values_copy =
508 isolate->factory()->CopyFixedArray(fixed_array_values); 508 isolate->factory()->CopyFixedArray(fixed_array_values);
509 copied_elements_values = fixed_array_values_copy; 509 copied_elements_values = fixed_array_values_copy;
510 for (int i = 0; i < fixed_array_values->length(); i++) { 510 for (int i = 0; i < fixed_array_values->length(); i++) {
511 Object* current = fixed_array_values->get(i); 511 Object* current = fixed_array_values->get(i);
512 if (current->IsFixedArray()) { 512 if (current->IsFixedArray()) {
513 // The value contains the constant_properties of a 513 // The value contains the constant_properties of a
514 // simple object or array literal. 514 // simple object or array literal.
515 Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i))); 515 Handle<FixedArray> fa(FixedArray::cast(fixed_array_values->get(i)));
516 Handle<Object> result = 516 Handle<Object> result =
517 CreateLiteralBoilerplate(isolate, literals, fa); 517 CreateLiteralBoilerplate(isolate, literals, fa);
518 if (result.is_null()) return result; 518 if (result.is_null()) return result;
519 fixed_array_values_copy->set(i, *result); 519 fixed_array_values_copy->set(i, *result);
520 } 520 }
521 } 521 }
522 } 522 }
523 } 523 }
524 object->set_elements(*copied_elements_values); 524 object->set_elements(*copied_elements_values);
525 object->set_length(Smi::FromInt(copied_elements_values->length())); 525 object->set_length(Smi::FromInt(copied_elements_values->length()));
526 526
527 // Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is 527 // Ensure that the boilerplate object has FAST_*_ELEMENTS, unless the flag is
528 // on or the object is larger than the threshold. 528 // on or the object is larger than the threshold.
529 if (!FLAG_smi_only_arrays && 529 if (!FLAG_smi_only_arrays &&
530 constant_elements_values->length() < kSmiLiteralMinimumLength) { 530 constant_elements_values->length() < kSmiLiteralMinimumLength) {
531 ElementsKind elements_kind = object->GetElementsKind(); 531 ElementsKind elements_kind = object->GetElementsKind();
532 if (!IsFastObjectElementsKind(elements_kind)) { 532 if (!IsFastObjectElementsKind(elements_kind)) {
533 if (IsFastHoleyElementsKind(elements_kind)) { 533 if (IsFastHoleyElementsKind(elements_kind)) {
534 CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS, 534 CHECK(!TransitionElements(object, FAST_HOLEY_ELEMENTS,
535 isolate)->IsFailure()); 535 isolate)->IsFailure());
536 } else { 536 } else {
537 CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure()); 537 CHECK(!TransitionElements(object, FAST_ELEMENTS, isolate)->IsFailure());
538 } 538 }
539 } 539 }
540 } 540 }
541 541
542 object->ValidateElements(); 542 object->ValidateElements();
543 return object; 543 return object;
544 } 544 }
545 545
546 546
547 static Handle<Object> CreateLiteralBoilerplate( 547 static Handle<Object> CreateLiteralBoilerplate(
548 Isolate* isolate, 548 Isolate* isolate,
549 Handle<FixedArray> literals, 549 Handle<FixedArray> literals,
550 Handle<FixedArray> array) { 550 Handle<FixedArray> array) {
551 Handle<FixedArray> elements = CompileTimeValue::GetElements(array); 551 Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
552 const bool kHasNoFunctionLiteral = false; 552 const bool kHasNoFunctionLiteral = false;
553 switch (CompileTimeValue::GetType(array)) { 553 switch (CompileTimeValue::GetType(array)) {
554 case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS: 554 case CompileTimeValue::OBJECT_LITERAL_FAST_ELEMENTS:
555 return CreateObjectLiteralBoilerplate(isolate, 555 return CreateObjectLiteralBoilerplate(isolate,
556 literals, 556 literals,
557 elements, 557 elements,
558 true, 558 true,
559 kHasNoFunctionLiteral); 559 kHasNoFunctionLiteral);
560 case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS: 560 case CompileTimeValue::OBJECT_LITERAL_SLOW_ELEMENTS:
561 return CreateObjectLiteralBoilerplate(isolate, 561 return CreateObjectLiteralBoilerplate(isolate,
562 literals, 562 literals,
563 elements, 563 elements,
564 false, 564 false,
565 kHasNoFunctionLiteral); 565 kHasNoFunctionLiteral);
566 case CompileTimeValue::ARRAY_LITERAL: 566 case CompileTimeValue::ARRAY_LITERAL:
567 return Runtime::CreateArrayLiteralBoilerplate( 567 return Runtime::CreateArrayLiteralBoilerplate(
568 isolate, literals, elements); 568 isolate, literals, elements);
569 default: 569 default:
570 UNREACHABLE(); 570 UNREACHABLE();
571 return Handle<Object>::null(); 571 return Handle<Object>::null();
572 } 572 }
573 } 573 }
574 574
575 575
576 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) { 576 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteral) {
577 HandleScope scope(isolate); 577 HandleScope scope(isolate);
578 ASSERT(args.length() == 4); 578 ASSERT(args.length() == 4);
579 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); 579 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
580 CONVERT_SMI_ARG_CHECKED(literals_index, 1); 580 CONVERT_SMI_ARG_CHECKED(literals_index, 1);
581 CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2); 581 CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
582 CONVERT_SMI_ARG_CHECKED(flags, 3); 582 CONVERT_SMI_ARG_CHECKED(flags, 3);
583 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; 583 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
584 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0; 584 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
585 585
586 // Check if boilerplate exists. If not, create it first. 586 // Check if boilerplate exists. If not, create it first.
587 Handle<Object> boilerplate(literals->get(literals_index), isolate); 587 Handle<Object> boilerplate(literals->get(literals_index), isolate);
588 if (*boilerplate == isolate->heap()->undefined_value()) { 588 if (*boilerplate == isolate->heap()->undefined_value()) {
589 boilerplate = CreateObjectLiteralBoilerplate(isolate, 589 boilerplate = CreateObjectLiteralBoilerplate(isolate,
590 literals, 590 literals,
591 constant_properties, 591 constant_properties,
592 should_have_fast_elements, 592 should_have_fast_elements,
593 has_function_literal); 593 has_function_literal);
594 if (boilerplate.is_null()) return Failure::Exception(); 594 if (boilerplate.is_null()) return Failure::Exception();
595 // Update the functions literal and return the boilerplate. 595 // Update the functions literal and return the boilerplate.
596 literals->set(literals_index, *boilerplate); 596 literals->set(literals_index, *boilerplate);
597 } 597 }
598 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); 598 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
599 } 599 }
600 600
601 601
602 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) { 602 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateObjectLiteralShallow) {
603 HandleScope scope(isolate); 603 HandleScope scope(isolate);
604 ASSERT(args.length() == 4); 604 ASSERT(args.length() == 4);
605 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); 605 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
606 CONVERT_SMI_ARG_CHECKED(literals_index, 1); 606 CONVERT_SMI_ARG_CHECKED(literals_index, 1);
607 CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2); 607 CONVERT_ARG_HANDLE_CHECKED(FixedArray, constant_properties, 2);
608 CONVERT_SMI_ARG_CHECKED(flags, 3); 608 CONVERT_SMI_ARG_CHECKED(flags, 3);
609 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0; 609 bool should_have_fast_elements = (flags & ObjectLiteral::kFastElements) != 0;
610 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0; 610 bool has_function_literal = (flags & ObjectLiteral::kHasFunction) != 0;
611 611
612 // Check if boilerplate exists. If not, create it first. 612 // Check if boilerplate exists. If not, create it first.
613 Handle<Object> boilerplate(literals->get(literals_index), isolate); 613 Handle<Object> boilerplate(literals->get(literals_index), isolate);
614 if (*boilerplate == isolate->heap()->undefined_value()) { 614 if (*boilerplate == isolate->heap()->undefined_value()) {
615 boilerplate = CreateObjectLiteralBoilerplate(isolate, 615 boilerplate = CreateObjectLiteralBoilerplate(isolate,
616 literals, 616 literals,
617 constant_properties, 617 constant_properties,
618 should_have_fast_elements, 618 should_have_fast_elements,
619 has_function_literal); 619 has_function_literal);
620 if (boilerplate.is_null()) return Failure::Exception(); 620 if (boilerplate.is_null()) return Failure::Exception();
621 // Update the functions literal and return the boilerplate. 621 // Update the functions literal and return the boilerplate.
622 literals->set(literals_index, *boilerplate); 622 literals->set(literals_index, *boilerplate);
623 } 623 }
624 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate)); 624 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
625 } 625 }
626 626
627 627
628 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) { 628 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteral) {
629 HandleScope scope(isolate); 629 HandleScope scope(isolate);
630 ASSERT(args.length() == 3); 630 ASSERT(args.length() == 3);
631 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); 631 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
632 CONVERT_SMI_ARG_CHECKED(literals_index, 1); 632 CONVERT_SMI_ARG_CHECKED(literals_index, 1);
633 CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2); 633 CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
634 634
635 // Check if boilerplate exists. If not, create it first. 635 // Check if boilerplate exists. If not, create it first.
636 Handle<Object> boilerplate(literals->get(literals_index), isolate); 636 Handle<Object> boilerplate(literals->get(literals_index), isolate);
637 if (*boilerplate == isolate->heap()->undefined_value()) { 637 if (*boilerplate == isolate->heap()->undefined_value()) {
638 ASSERT(*elements != isolate->heap()->empty_fixed_array()); 638 ASSERT(*elements != isolate->heap()->empty_fixed_array());
639 boilerplate = 639 boilerplate =
640 Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements); 640 Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
641 if (boilerplate.is_null()) return Failure::Exception(); 641 if (boilerplate.is_null()) return Failure::Exception();
642 // Update the functions literal and return the boilerplate. 642 // Update the functions literal and return the boilerplate.
643 literals->set(literals_index, *boilerplate); 643 literals->set(literals_index, *boilerplate);
644 } 644 }
645 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate)); 645 return DeepCopyBoilerplate(isolate, JSObject::cast(*boilerplate));
646 } 646 }
647 647
648 648
649 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) { 649 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
650 HandleScope scope(isolate); 650 HandleScope scope(isolate);
651 ASSERT(args.length() == 3); 651 ASSERT(args.length() == 3);
652 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); 652 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
653 CONVERT_SMI_ARG_CHECKED(literals_index, 1); 653 CONVERT_SMI_ARG_CHECKED(literals_index, 1);
654 CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2); 654 CONVERT_ARG_HANDLE_CHECKED(FixedArray, elements, 2);
655 655
656 // Check if boilerplate exists. If not, create it first. 656 // Check if boilerplate exists. If not, create it first.
657 Handle<Object> boilerplate(literals->get(literals_index), isolate); 657 Handle<Object> boilerplate(literals->get(literals_index), isolate);
658 if (*boilerplate == isolate->heap()->undefined_value()) { 658 if (*boilerplate == isolate->heap()->undefined_value()) {
659 ASSERT(*elements != isolate->heap()->empty_fixed_array()); 659 ASSERT(*elements != isolate->heap()->empty_fixed_array());
660 boilerplate = 660 boilerplate =
661 Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements); 661 Runtime::CreateArrayLiteralBoilerplate(isolate, literals, elements);
662 if (boilerplate.is_null()) return Failure::Exception(); 662 if (boilerplate.is_null()) return Failure::Exception();
663 // Update the functions literal and return the boilerplate. 663 // Update the functions literal and return the boilerplate.
664 literals->set(literals_index, *boilerplate); 664 literals->set(literals_index, *boilerplate);
665 } 665 }
666 if (JSObject::cast(*boilerplate)->elements()->map() == 666 if (JSObject::cast(*boilerplate)->elements()->map() ==
667 isolate->heap()->fixed_cow_array_map()) { 667 isolate->heap()->fixed_cow_array_map()) {
668 isolate->counters()->cow_arrays_created_runtime()->Increment(); 668 isolate->counters()->cow_arrays_created_runtime()->Increment();
669 } 669 }
670 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate)); 670 return isolate->heap()->CopyJSObject(JSObject::cast(*boilerplate));
671 } 671 }
672 672
673 673
674 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) { 674 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
675 ASSERT(args.length() == 2); 675 ASSERT(args.length() == 2);
676 CONVERT_ARG_CHECKED(JSReceiver, handler, 0); 676 CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
677 Object* prototype = args[1]; 677 Object* prototype = args[1];
678 Object* used_prototype = 678 Object* used_prototype =
679 prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value(); 679 prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
680 return isolate->heap()->AllocateJSProxy(handler, used_prototype); 680 return isolate->heap()->AllocateJSProxy(handler, used_prototype);
681 } 681 }
682 682
683 683
684 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) { 684 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
685 ASSERT(args.length() == 4); 685 ASSERT(args.length() == 4);
686 CONVERT_ARG_CHECKED(JSReceiver, handler, 0); 686 CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
687 Object* call_trap = args[1]; 687 Object* call_trap = args[1];
688 RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy()); 688 RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
689 CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2); 689 CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
690 Object* prototype = args[3]; 690 Object* prototype = args[3];
691 Object* used_prototype = 691 Object* used_prototype =
692 prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value(); 692 prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
693 return isolate->heap()->AllocateJSFunctionProxy( 693 return isolate->heap()->AllocateJSFunctionProxy(
694 handler, call_trap, construct_trap, used_prototype); 694 handler, call_trap, construct_trap, used_prototype);
695 } 695 }
696 696
697 697
698 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) { 698 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSProxy) {
699 ASSERT(args.length() == 1); 699 ASSERT(args.length() == 1);
700 Object* obj = args[0]; 700 Object* obj = args[0];
701 return isolate->heap()->ToBoolean(obj->IsJSProxy()); 701 return isolate->heap()->ToBoolean(obj->IsJSProxy());
702 } 702 }
703 703
704 704
705 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) { 705 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsJSFunctionProxy) {
706 ASSERT(args.length() == 1); 706 ASSERT(args.length() == 1);
707 Object* obj = args[0]; 707 Object* obj = args[0];
708 return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy()); 708 return isolate->heap()->ToBoolean(obj->IsJSFunctionProxy());
709 } 709 }
710 710
711 711
712 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) { 712 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetHandler) {
713 ASSERT(args.length() == 1); 713 ASSERT(args.length() == 1);
714 CONVERT_ARG_CHECKED(JSProxy, proxy, 0); 714 CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
715 return proxy->handler(); 715 return proxy->handler();
716 } 716 }
717 717
718 718
719 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) { 719 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetCallTrap) {
720 ASSERT(args.length() == 1); 720 ASSERT(args.length() == 1);
721 CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0); 721 CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
722 return proxy->call_trap(); 722 return proxy->call_trap();
723 } 723 }
724 724
725 725
726 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) { 726 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetConstructTrap) {
727 ASSERT(args.length() == 1); 727 ASSERT(args.length() == 1);
728 CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0); 728 CONVERT_ARG_CHECKED(JSFunctionProxy, proxy, 0);
729 return proxy->construct_trap(); 729 return proxy->construct_trap();
730 } 730 }
731 731
732 732
733 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) { 733 RUNTIME_FUNCTION(MaybeObject*, Runtime_Fix) {
734 ASSERT(args.length() == 1); 734 ASSERT(args.length() == 1);
735 CONVERT_ARG_CHECKED(JSProxy, proxy, 0); 735 CONVERT_ARG_CHECKED(JSProxy, proxy, 0);
736 proxy->Fix(); 736 proxy->Fix();
737 return isolate->heap()->undefined_value(); 737 return isolate->heap()->undefined_value();
738 } 738 }
739 739
740 740
741 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) { 741 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetInitialize) {
742 HandleScope scope(isolate); 742 HandleScope scope(isolate);
743 ASSERT(args.length() == 1); 743 ASSERT(args.length() == 1);
744 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); 744 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
745 Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0); 745 Handle<ObjectHashSet> table = isolate->factory()->NewObjectHashSet(0);
746 holder->set_table(*table); 746 holder->set_table(*table);
747 return *holder; 747 return *holder;
748 } 748 }
749 749
750 750
751 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) { 751 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetAdd) {
752 HandleScope scope(isolate); 752 HandleScope scope(isolate);
753 ASSERT(args.length() == 2); 753 ASSERT(args.length() == 2);
754 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); 754 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
755 Handle<Object> key(args[1]); 755 Handle<Object> key(args[1]);
756 Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table())); 756 Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
757 table = ObjectHashSetAdd(table, key); 757 table = ObjectHashSetAdd(table, key);
758 holder->set_table(*table); 758 holder->set_table(*table);
759 return isolate->heap()->undefined_value(); 759 return isolate->heap()->undefined_value();
760 } 760 }
761 761
762 762
763 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) { 763 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetHas) {
764 HandleScope scope(isolate); 764 HandleScope scope(isolate);
765 ASSERT(args.length() == 2); 765 ASSERT(args.length() == 2);
766 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); 766 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
767 Handle<Object> key(args[1]); 767 Handle<Object> key(args[1]);
768 Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table())); 768 Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
769 return isolate->heap()->ToBoolean(table->Contains(*key)); 769 return isolate->heap()->ToBoolean(table->Contains(*key));
770 } 770 }
771 771
772 772
773 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) { 773 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetDelete) {
774 HandleScope scope(isolate); 774 HandleScope scope(isolate);
775 ASSERT(args.length() == 2); 775 ASSERT(args.length() == 2);
776 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0); 776 CONVERT_ARG_HANDLE_CHECKED(JSSet, holder, 0);
777 Handle<Object> key(args[1]); 777 Handle<Object> key(args[1]);
778 Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table())); 778 Handle<ObjectHashSet> table(ObjectHashSet::cast(holder->table()));
779 table = ObjectHashSetRemove(table, key); 779 table = ObjectHashSetRemove(table, key);
780 holder->set_table(*table); 780 holder->set_table(*table);
781 return isolate->heap()->undefined_value(); 781 return isolate->heap()->undefined_value();
782 } 782 }
783 783
784 784
785 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) { 785 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapInitialize) {
786 HandleScope scope(isolate); 786 HandleScope scope(isolate);
787 ASSERT(args.length() == 1); 787 ASSERT(args.length() == 1);
788 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); 788 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
789 Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0); 789 Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
790 holder->set_table(*table); 790 holder->set_table(*table);
791 return *holder; 791 return *holder;
792 } 792 }
793 793
794 794
795 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) { 795 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapGet) {
796 HandleScope scope(isolate); 796 HandleScope scope(isolate);
797 ASSERT(args.length() == 2); 797 ASSERT(args.length() == 2);
798 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); 798 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
799 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 799 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
800 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table())); 800 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
801 Handle<Object> lookup(table->Lookup(*key)); 801 Handle<Object> lookup(table->Lookup(*key));
802 return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup; 802 return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
803 } 803 }
804 804
805 805
806 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) { 806 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapHas) {
807 HandleScope scope(isolate); 807 HandleScope scope(isolate);
808 ASSERT(args.length() == 2); 808 ASSERT(args.length() == 2);
809 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); 809 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
810 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 810 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
811 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table())); 811 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
812 Handle<Object> lookup(table->Lookup(*key)); 812 Handle<Object> lookup(table->Lookup(*key));
813 return isolate->heap()->ToBoolean(!lookup->IsTheHole()); 813 return isolate->heap()->ToBoolean(!lookup->IsTheHole());
814 } 814 }
815 815
816 816
817 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) { 817 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapDelete) {
818 HandleScope scope(isolate); 818 HandleScope scope(isolate);
819 ASSERT(args.length() == 2); 819 ASSERT(args.length() == 2);
820 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); 820 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
821 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 821 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
822 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table())); 822 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
823 Handle<Object> lookup(table->Lookup(*key)); 823 Handle<Object> lookup(table->Lookup(*key));
824 Handle<ObjectHashTable> new_table = 824 Handle<ObjectHashTable> new_table =
825 PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value()); 825 PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
826 holder->set_table(*new_table); 826 holder->set_table(*new_table);
827 return isolate->heap()->ToBoolean(!lookup->IsTheHole()); 827 return isolate->heap()->ToBoolean(!lookup->IsTheHole());
828 } 828 }
829 829
830 830
831 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) { 831 RUNTIME_FUNCTION(MaybeObject*, Runtime_MapSet) {
832 HandleScope scope(isolate); 832 HandleScope scope(isolate);
833 ASSERT(args.length() == 3); 833 ASSERT(args.length() == 3);
834 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0); 834 CONVERT_ARG_HANDLE_CHECKED(JSMap, holder, 0);
835 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1); 835 CONVERT_ARG_HANDLE_CHECKED(Object, key, 1);
836 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2); 836 CONVERT_ARG_HANDLE_CHECKED(Object, value, 2);
837 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table())); 837 Handle<ObjectHashTable> table(ObjectHashTable::cast(holder->table()));
838 Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value); 838 Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
839 holder->set_table(*new_table); 839 holder->set_table(*new_table);
840 return isolate->heap()->undefined_value(); 840 return isolate->heap()->undefined_value();
841 } 841 }
842 842
843 843
844 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) { 844 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapInitialize) {
845 HandleScope scope(isolate); 845 HandleScope scope(isolate);
846 ASSERT(args.length() == 1); 846 ASSERT(args.length() == 1);
847 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0); 847 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
848 ASSERT(weakmap->map()->inobject_properties() == 0); 848 ASSERT(weakmap->map()->inobject_properties() == 0);
849 Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0); 849 Handle<ObjectHashTable> table = isolate->factory()->NewObjectHashTable(0);
850 weakmap->set_table(*table); 850 weakmap->set_table(*table);
851 weakmap->set_next(Smi::FromInt(0)); 851 weakmap->set_next(Smi::FromInt(0));
852 return *weakmap; 852 return *weakmap;
853 } 853 }
854 854
855 855
856 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) { 856 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapGet) {
857 HandleScope scope(isolate); 857 HandleScope scope(isolate);
858 ASSERT(args.length() == 2); 858 ASSERT(args.length() == 2);
859 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0); 859 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
860 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1); 860 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
861 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table())); 861 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
862 Handle<Object> lookup(table->Lookup(*key)); 862 Handle<Object> lookup(table->Lookup(*key));
863 return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup; 863 return lookup->IsTheHole() ? isolate->heap()->undefined_value() : *lookup;
864 } 864 }
865 865
866 866
867 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapHas) { 867 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapHas) {
868 HandleScope scope(isolate); 868 HandleScope scope(isolate);
869 ASSERT(args.length() == 2); 869 ASSERT(args.length() == 2);
870 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0); 870 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
871 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1); 871 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
872 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table())); 872 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
873 Handle<Object> lookup(table->Lookup(*key)); 873 Handle<Object> lookup(table->Lookup(*key));
874 return isolate->heap()->ToBoolean(!lookup->IsTheHole()); 874 return isolate->heap()->ToBoolean(!lookup->IsTheHole());
875 } 875 }
876 876
877 877
878 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapDelete) { 878 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapDelete) {
879 HandleScope scope(isolate); 879 HandleScope scope(isolate);
880 ASSERT(args.length() == 2); 880 ASSERT(args.length() == 2);
881 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0); 881 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
882 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1); 882 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
883 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table())); 883 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
884 Handle<Object> lookup(table->Lookup(*key)); 884 Handle<Object> lookup(table->Lookup(*key));
885 Handle<ObjectHashTable> new_table = 885 Handle<ObjectHashTable> new_table =
886 PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value()); 886 PutIntoObjectHashTable(table, key, isolate->factory()->the_hole_value());
887 weakmap->set_table(*new_table); 887 weakmap->set_table(*new_table);
888 return isolate->heap()->ToBoolean(!lookup->IsTheHole()); 888 return isolate->heap()->ToBoolean(!lookup->IsTheHole());
889 } 889 }
890 890
891 891
892 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) { 892 RUNTIME_FUNCTION(MaybeObject*, Runtime_WeakMapSet) {
893 HandleScope scope(isolate); 893 HandleScope scope(isolate);
894 ASSERT(args.length() == 3); 894 ASSERT(args.length() == 3);
895 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0); 895 CONVERT_ARG_HANDLE_CHECKED(JSWeakMap, weakmap, 0);
896 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1); 896 CONVERT_ARG_HANDLE_CHECKED(JSReceiver, key, 1);
897 Handle<Object> value(args[2]); 897 Handle<Object> value(args[2]);
898 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table())); 898 Handle<ObjectHashTable> table(ObjectHashTable::cast(weakmap->table()));
899 Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value); 899 Handle<ObjectHashTable> new_table = PutIntoObjectHashTable(table, key, value);
900 weakmap->set_table(*new_table); 900 weakmap->set_table(*new_table);
901 return isolate->heap()->undefined_value(); 901 return isolate->heap()->undefined_value();
902 } 902 }
903 903
904 904
905 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) { 905 RUNTIME_FUNCTION(MaybeObject*, Runtime_ClassOf) {
906 NoHandleAllocation ha; 906 NoHandleAllocation ha;
907 ASSERT(args.length() == 1); 907 ASSERT(args.length() == 1);
908 Object* obj = args[0]; 908 Object* obj = args[0];
909 if (!obj->IsJSObject()) return isolate->heap()->null_value(); 909 if (!obj->IsJSObject()) return isolate->heap()->null_value();
910 return JSObject::cast(obj)->class_name(); 910 return JSObject::cast(obj)->class_name();
911 } 911 }
912 912
913 913
914 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) { 914 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetPrototype) {
915 NoHandleAllocation ha; 915 NoHandleAllocation ha;
916 ASSERT(args.length() == 1); 916 ASSERT(args.length() == 1);
917 CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0); 917 CONVERT_ARG_CHECKED(JSReceiver, input_obj, 0);
918 Object* obj = input_obj; 918 Object* obj = input_obj;
919 // We don't expect access checks to be needed on JSProxy objects. 919 // We don't expect access checks to be needed on JSProxy objects.
920 ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject()); 920 ASSERT(!obj->IsAccessCheckNeeded() || obj->IsJSObject());
921 do { 921 do {
922 if (obj->IsAccessCheckNeeded() && 922 if (obj->IsAccessCheckNeeded() &&
923 !isolate->MayNamedAccess(JSObject::cast(obj), 923 !isolate->MayNamedAccess(JSObject::cast(obj),
924 isolate->heap()->Proto_symbol(), 924 isolate->heap()->Proto_symbol(),
925 v8::ACCESS_GET)) { 925 v8::ACCESS_GET)) {
926 isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET); 926 isolate->ReportFailedAccessCheck(JSObject::cast(obj), v8::ACCESS_GET);
927 return isolate->heap()->undefined_value(); 927 return isolate->heap()->undefined_value();
928 } 928 }
929 obj = obj->GetPrototype(); 929 obj = obj->GetPrototype();
930 } while (obj->IsJSObject() && 930 } while (obj->IsJSObject() &&
931 JSObject::cast(obj)->map()->is_hidden_prototype()); 931 JSObject::cast(obj)->map()->is_hidden_prototype());
932 return obj; 932 return obj;
933 } 933 }
934 934
935 935
936 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) { 936 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsInPrototypeChain) {
937 NoHandleAllocation ha; 937 NoHandleAllocation ha;
938 ASSERT(args.length() == 2); 938 ASSERT(args.length() == 2);
939 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8). 939 // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).
940 Object* O = args[0]; 940 Object* O = args[0];
941 Object* V = args[1]; 941 Object* V = args[1];
942 while (true) { 942 while (true) {
943 Object* prototype = V->GetPrototype(); 943 Object* prototype = V->GetPrototype();
944 if (prototype->IsNull()) return isolate->heap()->false_value(); 944 if (prototype->IsNull()) return isolate->heap()->false_value();
945 if (O == prototype) return isolate->heap()->true_value(); 945 if (O == prototype) return isolate->heap()->true_value();
946 V = prototype; 946 V = prototype;
947 } 947 }
948 } 948 }
949 949
950 950
951 // Recursively traverses hidden prototypes if property is not found 951 // Recursively traverses hidden prototypes if property is not found
952 static void GetOwnPropertyImplementation(JSObject* obj, 952 static void GetOwnPropertyImplementation(JSObject* obj,
953 String* name, 953 String* name,
954 LookupResult* result) { 954 LookupResult* result) {
955 obj->LocalLookupRealNamedProperty(name, result); 955 obj->LocalLookupRealNamedProperty(name, result);
956 956
957 if (result->IsFound()) return; 957 if (result->IsFound()) return;
958 958
959 Object* proto = obj->GetPrototype(); 959 Object* proto = obj->GetPrototype();
960 if (proto->IsJSObject() && 960 if (proto->IsJSObject() &&
961 JSObject::cast(proto)->map()->is_hidden_prototype()) 961 JSObject::cast(proto)->map()->is_hidden_prototype())
962 GetOwnPropertyImplementation(JSObject::cast(proto), 962 GetOwnPropertyImplementation(JSObject::cast(proto),
963 name, result); 963 name, result);
964 } 964 }
965 965
966 966
967 static bool CheckAccessException(LookupResult* result, 967 static bool CheckAccessException(LookupResult* result,
968 v8::AccessType access_type) { 968 v8::AccessType access_type) {
969 if (result->type() == CALLBACKS) { 969 if (result->type() == CALLBACKS) {
970 Object* callback = result->GetCallbackObject(); 970 Object* callback = result->GetCallbackObject();
971 if (callback->IsAccessorInfo()) { 971 if (callback->IsAccessorInfo()) {
972 AccessorInfo* info = AccessorInfo::cast(callback); 972 AccessorInfo* info = AccessorInfo::cast(callback);
973 bool can_access = 973 bool can_access =
974 (access_type == v8::ACCESS_HAS && 974 (access_type == v8::ACCESS_HAS &&
975 (info->all_can_read() || info->all_can_write())) || 975 (info->all_can_read() || info->all_can_write())) ||
976 (access_type == v8::ACCESS_GET && info->all_can_read()) || 976 (access_type == v8::ACCESS_GET && info->all_can_read()) ||
977 (access_type == v8::ACCESS_SET && info->all_can_write()); 977 (access_type == v8::ACCESS_SET && info->all_can_write());
978 return can_access; 978 return can_access;
979 } 979 }
980 } 980 }
981 981
982 return false; 982 return false;
983 } 983 }
984 984
985 985
986 static bool CheckAccess(JSObject* obj, 986 static bool CheckAccess(JSObject* obj,
987 String* name, 987 String* name,
988 LookupResult* result, 988 LookupResult* result,
989 v8::AccessType access_type) { 989 v8::AccessType access_type) {
990 ASSERT(result->IsProperty()); 990 ASSERT(result->IsProperty());
991 991
992 JSObject* holder = result->holder(); 992 JSObject* holder = result->holder();
993 JSObject* current = obj; 993 JSObject* current = obj;
994 Isolate* isolate = obj->GetIsolate(); 994 Isolate* isolate = obj->GetIsolate();
995 while (true) { 995 while (true) {
996 if (current->IsAccessCheckNeeded() && 996 if (current->IsAccessCheckNeeded() &&
997 !isolate->MayNamedAccess(current, name, access_type)) { 997 !isolate->MayNamedAccess(current, name, access_type)) {
998 // Access check callback denied the access, but some properties 998 // Access check callback denied the access, but some properties
999 // can have a special permissions which override callbacks descision 999 // can have a special permissions which override callbacks descision
1000 // (currently see v8::AccessControl). 1000 // (currently see v8::AccessControl).
1001 break; 1001 break;
1002 } 1002 }
1003 1003
1004 if (current == holder) { 1004 if (current == holder) {
1005 return true; 1005 return true;
1006 } 1006 }
1007 1007
1008 current = JSObject::cast(current->GetPrototype()); 1008 current = JSObject::cast(current->GetPrototype());
1009 } 1009 }
1010 1010
1011 // API callbacks can have per callback access exceptions. 1011 // API callbacks can have per callback access exceptions.
1012 switch (result->type()) { 1012 switch (result->type()) {
1013 case CALLBACKS: { 1013 case CALLBACKS: {
1014 if (CheckAccessException(result, access_type)) { 1014 if (CheckAccessException(result, access_type)) {
1015 return true; 1015 return true;
1016 } 1016 }
1017 break; 1017 break;
1018 } 1018 }
1019 case INTERCEPTOR: { 1019 case INTERCEPTOR: {
1020 // If the object has an interceptor, try real named properties. 1020 // If the object has an interceptor, try real named properties.
1021 // Overwrite the result to fetch the correct property later. 1021 // Overwrite the result to fetch the correct property later.
1022 holder->LookupRealNamedProperty(name, result); 1022 holder->LookupRealNamedProperty(name, result);
1023 if (result->IsProperty()) { 1023 if (result->IsProperty()) {
1024 if (CheckAccessException(result, access_type)) { 1024 if (CheckAccessException(result, access_type)) {
1025 return true; 1025 return true;
1026 } 1026 }
1027 } 1027 }
1028 break; 1028 break;
1029 } 1029 }
1030 default: 1030 default:
1031 break; 1031 break;
1032 } 1032 }
1033 1033
1034 isolate->ReportFailedAccessCheck(current, access_type); 1034 isolate->ReportFailedAccessCheck(current, access_type);
1035 return false; 1035 return false;
1036 } 1036 }
1037 1037
1038 1038
1039 // TODO(1095): we should traverse hidden prototype hierachy as well. 1039 // TODO(1095): we should traverse hidden prototype hierachy as well.
1040 static bool CheckElementAccess(JSObject* obj, 1040 static bool CheckElementAccess(JSObject* obj,
1041 uint32_t index, 1041 uint32_t index,
1042 v8::AccessType access_type) { 1042 v8::AccessType access_type) {
1043 if (obj->IsAccessCheckNeeded() && 1043 if (obj->IsAccessCheckNeeded() &&
1044 !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) { 1044 !obj->GetIsolate()->MayIndexedAccess(obj, index, access_type)) {
1045 return false; 1045 return false;
1046 } 1046 }
1047 1047
1048 return true; 1048 return true;
1049 } 1049 }
1050 1050
1051 1051
1052 // Enumerator used as indices into the array returned from GetOwnProperty 1052 // Enumerator used as indices into the array returned from GetOwnProperty
1053 enum PropertyDescriptorIndices { 1053 enum PropertyDescriptorIndices {
1054 IS_ACCESSOR_INDEX, 1054 IS_ACCESSOR_INDEX,
1055 VALUE_INDEX, 1055 VALUE_INDEX,
1056 GETTER_INDEX, 1056 GETTER_INDEX,
1057 SETTER_INDEX, 1057 SETTER_INDEX,
1058 WRITABLE_INDEX, 1058 WRITABLE_INDEX,
1059 ENUMERABLE_INDEX, 1059 ENUMERABLE_INDEX,
1060 CONFIGURABLE_INDEX, 1060 CONFIGURABLE_INDEX,
1061 DESCRIPTOR_SIZE 1061 DESCRIPTOR_SIZE
1062 }; 1062 };
1063 1063
1064 1064
1065 static MaybeObject* GetOwnProperty(Isolate* isolate, 1065 static MaybeObject* GetOwnProperty(Isolate* isolate,
1066 Handle<JSObject> obj, 1066 Handle<JSObject> obj,
1067 Handle<String> name) { 1067 Handle<String> name) {
1068 Heap* heap = isolate->heap(); 1068 Heap* heap = isolate->heap();
1069 Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE); 1069 Handle<FixedArray> elms = isolate->factory()->NewFixedArray(DESCRIPTOR_SIZE);
1070 Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms); 1070 Handle<JSArray> desc = isolate->factory()->NewJSArrayWithElements(elms);
1071 LookupResult result(isolate); 1071 LookupResult result(isolate);
1072 // This could be an element. 1072 // This could be an element.
1073 uint32_t index; 1073 uint32_t index;
1074 if (name->AsArrayIndex(&index)) { 1074 if (name->AsArrayIndex(&index)) {
1075 switch (obj->HasLocalElement(index)) { 1075 switch (obj->HasLocalElement(index)) {
1076 case JSObject::UNDEFINED_ELEMENT: 1076 case JSObject::UNDEFINED_ELEMENT:
1077 return heap->undefined_value(); 1077 return heap->undefined_value();
1078 1078
1079 case JSObject::STRING_CHARACTER_ELEMENT: { 1079 case JSObject::STRING_CHARACTER_ELEMENT: {
1080 // Special handling of string objects according to ECMAScript 5 1080 // Special handling of string objects according to ECMAScript 5
1081 // 15.5.5.2. Note that this might be a string object with elements 1081 // 15.5.5.2. Note that this might be a string object with elements
1082 // other than the actual string value. This is covered by the 1082 // other than the actual string value. This is covered by the
1083 // subsequent cases. 1083 // subsequent cases.
1084 Handle<JSValue> js_value = Handle<JSValue>::cast(obj); 1084 Handle<JSValue> js_value = Handle<JSValue>::cast(obj);
1085 Handle<String> str(String::cast(js_value->value())); 1085 Handle<String> str(String::cast(js_value->value()));
1086 Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED); 1086 Handle<String> substr = SubString(str, index, index + 1, NOT_TENURED);
1087 1087
1088 elms->set(IS_ACCESSOR_INDEX, heap->false_value()); 1088 elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1089 elms->set(VALUE_INDEX, *substr); 1089 elms->set(VALUE_INDEX, *substr);
1090 elms->set(WRITABLE_INDEX, heap->false_value()); 1090 elms->set(WRITABLE_INDEX, heap->false_value());
1091 elms->set(ENUMERABLE_INDEX, heap->true_value()); 1091 elms->set(ENUMERABLE_INDEX, heap->true_value());
1092 elms->set(CONFIGURABLE_INDEX, heap->false_value()); 1092 elms->set(CONFIGURABLE_INDEX, heap->false_value());
1093 return *desc; 1093 return *desc;
1094 } 1094 }
1095 1095
1096 case JSObject::INTERCEPTED_ELEMENT: 1096 case JSObject::INTERCEPTED_ELEMENT:
1097 case JSObject::FAST_ELEMENT: { 1097 case JSObject::FAST_ELEMENT: {
1098 elms->set(IS_ACCESSOR_INDEX, heap->false_value()); 1098 elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1099 Handle<Object> value = Object::GetElement(obj, index); 1099 Handle<Object> value = Object::GetElement(obj, index);
1100 RETURN_IF_EMPTY_HANDLE(isolate, value); 1100 RETURN_IF_EMPTY_HANDLE(isolate, value);
1101 elms->set(VALUE_INDEX, *value); 1101 elms->set(VALUE_INDEX, *value);
1102 elms->set(WRITABLE_INDEX, heap->true_value()); 1102 elms->set(WRITABLE_INDEX, heap->true_value());
1103 elms->set(ENUMERABLE_INDEX, heap->true_value()); 1103 elms->set(ENUMERABLE_INDEX, heap->true_value());
1104 elms->set(CONFIGURABLE_INDEX, heap->true_value()); 1104 elms->set(CONFIGURABLE_INDEX, heap->true_value());
1105 return *desc; 1105 return *desc;
1106 } 1106 }
1107 1107
1108 case JSObject::DICTIONARY_ELEMENT: { 1108 case JSObject::DICTIONARY_ELEMENT: {
1109 Handle<JSObject> holder = obj; 1109 Handle<JSObject> holder = obj;
1110 if (obj->IsJSGlobalProxy()) { 1110 if (obj->IsJSGlobalProxy()) {
1111 Object* proto = obj->GetPrototype(); 1111 Object* proto = obj->GetPrototype();
1112 if (proto->IsNull()) return heap->undefined_value(); 1112 if (proto->IsNull()) return heap->undefined_value();
1113 ASSERT(proto->IsJSGlobalObject()); 1113 ASSERT(proto->IsJSGlobalObject());
1114 holder = Handle<JSObject>(JSObject::cast(proto)); 1114 holder = Handle<JSObject>(JSObject::cast(proto));
1115 } 1115 }
1116 FixedArray* elements = FixedArray::cast(holder->elements()); 1116 FixedArray* elements = FixedArray::cast(holder->elements());
1117 SeededNumberDictionary* dictionary = NULL; 1117 SeededNumberDictionary* dictionary = NULL;
1118 if (elements->map() == heap->non_strict_arguments_elements_map()) { 1118 if (elements->map() == heap->non_strict_arguments_elements_map()) {
1119 dictionary = SeededNumberDictionary::cast(elements->get(1)); 1119 dictionary = SeededNumberDictionary::cast(elements->get(1));
1120 } else { 1120 } else {
1121 dictionary = SeededNumberDictionary::cast(elements); 1121 dictionary = SeededNumberDictionary::cast(elements);
1122 } 1122 }
1123 int entry = dictionary->FindEntry(index); 1123 int entry = dictionary->FindEntry(index);
1124 ASSERT(entry != SeededNumberDictionary::kNotFound); 1124 ASSERT(entry != SeededNumberDictionary::kNotFound);
1125 PropertyDetails details = dictionary->DetailsAt(entry); 1125 PropertyDetails details = dictionary->DetailsAt(entry);
1126 switch (details.type()) { 1126 switch (details.type()) {
1127 case CALLBACKS: { 1127 case CALLBACKS: {
1128 // This is an accessor property with getter and/or setter. 1128 // This is an accessor property with getter and/or setter.
1129 AccessorPair* accessors = 1129 AccessorPair* accessors =
1130 AccessorPair::cast(dictionary->ValueAt(entry)); 1130 AccessorPair::cast(dictionary->ValueAt(entry));
1131 elms->set(IS_ACCESSOR_INDEX, heap->true_value()); 1131 elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1132 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) { 1132 if (CheckElementAccess(*obj, index, v8::ACCESS_GET)) {
1133 elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER)); 1133 elms->set(GETTER_INDEX, accessors->GetComponent(ACCESSOR_GETTER));
1134 } 1134 }
1135 if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) { 1135 if (CheckElementAccess(*obj, index, v8::ACCESS_SET)) {
1136 elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER)); 1136 elms->set(SETTER_INDEX, accessors->GetComponent(ACCESSOR_SETTER));
1137 } 1137 }
1138 break; 1138 break;
1139 } 1139 }
1140 case NORMAL: { 1140 case NORMAL: {
1141 // This is a data property. 1141 // This is a data property.
1142 elms->set(IS_ACCESSOR_INDEX, heap->false_value()); 1142 elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1143 Handle<Object> value = Object::GetElement(obj, index); 1143 Handle<Object> value = Object::GetElement(obj, index);
1144 ASSERT(!value.is_null()); 1144 ASSERT(!value.is_null());
1145 elms->set(VALUE_INDEX, *value); 1145 elms->set(VALUE_INDEX, *value);
1146 elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly())); 1146 elms->set(WRITABLE_INDEX, heap->ToBoolean(!details.IsReadOnly()));
1147 break; 1147 break;
1148 } 1148 }
1149 default: 1149 default:
1150 UNREACHABLE(); 1150 UNREACHABLE();
1151 break; 1151 break;
1152 } 1152 }
1153 elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum())); 1153 elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!details.IsDontEnum()));
1154 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete())); 1154 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!details.IsDontDelete()));
1155 return *desc; 1155 return *desc;
1156 } 1156 }
1157 } 1157 }
1158 } 1158 }
1159 1159
1160 // Use recursive implementation to also traverse hidden prototypes 1160 // Use recursive implementation to also traverse hidden prototypes
1161 GetOwnPropertyImplementation(*obj, *name, &result); 1161 GetOwnPropertyImplementation(*obj, *name, &result);
1162 1162
1163 if (!result.IsProperty()) { 1163 if (!result.IsProperty()) {
1164 return heap->undefined_value(); 1164 return heap->undefined_value();
1165 } 1165 }
1166 1166
1167 if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) { 1167 if (!CheckAccess(*obj, *name, &result, v8::ACCESS_HAS)) {
1168 return heap->false_value(); 1168 return heap->false_value();
1169 } 1169 }
1170 1170
1171 elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum())); 1171 elms->set(ENUMERABLE_INDEX, heap->ToBoolean(!result.IsDontEnum()));
1172 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete())); 1172 elms->set(CONFIGURABLE_INDEX, heap->ToBoolean(!result.IsDontDelete()));
1173 1173
1174 bool is_js_accessor = result.IsPropertyCallbacks() && 1174 bool is_js_accessor = result.IsPropertyCallbacks() &&
1175 (result.GetCallbackObject()->IsAccessorPair()); 1175 (result.GetCallbackObject()->IsAccessorPair());
1176 1176
1177 if (is_js_accessor) { 1177 if (is_js_accessor) {
1178 // __defineGetter__/__defineSetter__ callback. 1178 // __defineGetter__/__defineSetter__ callback.
1179 elms->set(IS_ACCESSOR_INDEX, heap->true_value()); 1179 elms->set(IS_ACCESSOR_INDEX, heap->true_value());
1180 1180
1181 AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject()); 1181 AccessorPair* accessors = AccessorPair::cast(result.GetCallbackObject());
1182 Object* getter = accessors->GetComponent(ACCESSOR_GETTER); 1182 Object* getter = accessors->GetComponent(ACCESSOR_GETTER);
1183 if (!getter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) { 1183 if (!getter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_GET)) {
1184 elms->set(GETTER_INDEX, getter); 1184 elms->set(GETTER_INDEX, getter);
1185 } 1185 }
1186 Object* setter = accessors->GetComponent(ACCESSOR_SETTER); 1186 Object* setter = accessors->GetComponent(ACCESSOR_SETTER);
1187 if (!setter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) { 1187 if (!setter->IsMap() && CheckAccess(*obj, *name, &result, v8::ACCESS_SET)) {
1188 elms->set(SETTER_INDEX, setter); 1188 elms->set(SETTER_INDEX, setter);
1189 } 1189 }
1190 } else { 1190 } else {
1191 elms->set(IS_ACCESSOR_INDEX, heap->false_value()); 1191 elms->set(IS_ACCESSOR_INDEX, heap->false_value());
1192 elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly())); 1192 elms->set(WRITABLE_INDEX, heap->ToBoolean(!result.IsReadOnly()));
1193 1193
1194 PropertyAttributes attrs; 1194 PropertyAttributes attrs;
1195 Object* value; 1195 Object* value;
1196 // GetProperty will check access and report any violations. 1196 // GetProperty will check access and report any violations.
1197 { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs); 1197 { MaybeObject* maybe_value = obj->GetProperty(*obj, &result, *name, &attrs);
1198 if (!maybe_value->ToObject(&value)) return maybe_value; 1198 if (!maybe_value->ToObject(&value)) return maybe_value;
1199 } 1199 }
1200 elms->set(VALUE_INDEX, value); 1200 elms->set(VALUE_INDEX, value);
1201 } 1201 }
1202 1202
1203 return *desc; 1203 return *desc;
1204 } 1204 }
1205 1205
1206 1206
1207 // Returns an array with the property description: 1207 // Returns an array with the property description:
1208 // if args[1] is not a property on args[0] 1208 // if args[1] is not a property on args[0]
1209 // returns undefined 1209 // returns undefined
1210 // if args[1] is a data property on args[0] 1210 // if args[1] is a data property on args[0]
1211 // [false, value, Writeable, Enumerable, Configurable] 1211 // [false, value, Writeable, Enumerable, Configurable]
1212 // if args[1] is an accessor on args[0] 1212 // if args[1] is an accessor on args[0]
1213 // [true, GetFunction, SetFunction, Enumerable, Configurable] 1213 // [true, GetFunction, SetFunction, Enumerable, Configurable]
1214 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) { 1214 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOwnProperty) {
1215 ASSERT(args.length() == 2); 1215 ASSERT(args.length() == 2);
1216 HandleScope scope(isolate); 1216 HandleScope scope(isolate);
1217 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); 1217 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
1218 CONVERT_ARG_HANDLE_CHECKED(String, name, 1); 1218 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
1219 return GetOwnProperty(isolate, obj, name); 1219 return GetOwnProperty(isolate, obj, name);
1220 } 1220 }
1221 1221
1222 1222
1223 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) { 1223 RUNTIME_FUNCTION(MaybeObject*, Runtime_PreventExtensions) {
1224 ASSERT(args.length() == 1); 1224 ASSERT(args.length() == 1);
1225 CONVERT_ARG_CHECKED(JSObject, obj, 0); 1225 CONVERT_ARG_CHECKED(JSObject, obj, 0);
1226 return obj->PreventExtensions(); 1226 return obj->PreventExtensions();
1227 } 1227 }
1228 1228
1229 1229
1230 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) { 1230 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsExtensible) {
1231 ASSERT(args.length() == 1); 1231 ASSERT(args.length() == 1);
1232 CONVERT_ARG_CHECKED(JSObject, obj, 0); 1232 CONVERT_ARG_CHECKED(JSObject, obj, 0);
1233 if (obj->IsJSGlobalProxy()) { 1233 if (obj->IsJSGlobalProxy()) {
1234 Object* proto = obj->GetPrototype(); 1234 Object* proto = obj->GetPrototype();
1235 if (proto->IsNull()) return isolate->heap()->false_value(); 1235 if (proto->IsNull()) return isolate->heap()->false_value();
1236 ASSERT(proto->IsJSGlobalObject()); 1236 ASSERT(proto->IsJSGlobalObject());
1237 obj = JSObject::cast(proto); 1237 obj = JSObject::cast(proto);
1238 } 1238 }
1239 return isolate->heap()->ToBoolean(obj->map()->is_extensible()); 1239 return isolate->heap()->ToBoolean(obj->map()->is_extensible());
1240 } 1240 }
1241 1241
1242 1242
1243 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) { 1243 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpCompile) {
1244 HandleScope scope(isolate); 1244 HandleScope scope(isolate);
1245 ASSERT(args.length() == 3); 1245 ASSERT(args.length() == 3);
1246 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0); 1246 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0);
1247 CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1); 1247 CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
1248 CONVERT_ARG_HANDLE_CHECKED(String, flags, 2); 1248 CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
1249 Handle<Object> result = 1249 Handle<Object> result =
1250 RegExpImpl::Compile(re, pattern, flags, isolate->runtime_zone()); 1250 RegExpImpl::Compile(re, pattern, flags, isolate->runtime_zone());
1251 if (result.is_null()) return Failure::Exception(); 1251 if (result.is_null()) return Failure::Exception();
1252 return *result; 1252 return *result;
1253 } 1253 }
1254 1254
1255 1255
1256 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) { 1256 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateApiFunction) {
1257 HandleScope scope(isolate); 1257 HandleScope scope(isolate);
1258 ASSERT(args.length() == 1); 1258 ASSERT(args.length() == 1);
1259 CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0); 1259 CONVERT_ARG_HANDLE_CHECKED(FunctionTemplateInfo, data, 0);
1260 return *isolate->factory()->CreateApiFunction(data); 1260 return *isolate->factory()->CreateApiFunction(data);
1261 } 1261 }
1262 1262
1263 1263
1264 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) { 1264 RUNTIME_FUNCTION(MaybeObject*, Runtime_IsTemplate) {
1265 ASSERT(args.length() == 1); 1265 ASSERT(args.length() == 1);
1266 Object* arg = args[0]; 1266 Object* arg = args[0];
1267 bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo(); 1267 bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
1268 return isolate->heap()->ToBoolean(result); 1268 return isolate->heap()->ToBoolean(result);
1269 } 1269 }
1270 1270
1271 1271
1272 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) { 1272 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetTemplateField) {
1273 ASSERT(args.length() == 2); 1273 ASSERT(args.length() == 2);
1274 CONVERT_ARG_CHECKED(HeapObject, templ, 0); 1274 CONVERT_ARG_CHECKED(HeapObject, templ, 0);
1275 CONVERT_SMI_ARG_CHECKED(index, 1) 1275 CONVERT_SMI_ARG_CHECKED(index, 1)
1276 int offset = index * kPointerSize + HeapObject::kHeaderSize; 1276 int offset = index * kPointerSize + HeapObject::kHeaderSize;
1277 InstanceType type = templ->map()->instance_type(); 1277 InstanceType type = templ->map()->instance_type();
1278 RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE || 1278 RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
1279 type == OBJECT_TEMPLATE_INFO_TYPE); 1279 type == OBJECT_TEMPLATE_INFO_TYPE);
1280 RUNTIME_ASSERT(offset > 0); 1280 RUNTIME_ASSERT(offset > 0);
1281 if (type == FUNCTION_TEMPLATE_INFO_TYPE) { 1281 if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
1282 RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize); 1282 RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
1283 } else { 1283 } else {
1284 RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize); 1284 RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
1285 } 1285 }
1286 return *HeapObject::RawField(templ, offset); 1286 return *HeapObject::RawField(templ, offset);
1287 } 1287 }
1288 1288
1289 1289
1290 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) { 1290 RUNTIME_FUNCTION(MaybeObject*, Runtime_DisableAccessChecks) {
1291 ASSERT(args.length() == 1); 1291 ASSERT(args.length() == 1);
1292 CONVERT_ARG_CHECKED(HeapObject, object, 0); 1292 CONVERT_ARG_CHECKED(HeapObject, object, 0);
1293 Map* old_map = object->map(); 1293 Map* old_map = object->map();
1294 bool needs_access_checks = old_map->is_access_check_needed(); 1294 bool needs_access_checks = old_map->is_access_check_needed();
1295 if (needs_access_checks) { 1295 if (needs_access_checks) {
1296 // Copy map so it won't interfere constructor's initial map. 1296 // Copy map so it won't interfere constructor's initial map.
1297 Map* new_map; 1297 Map* new_map;
1298 MaybeObject* maybe_new_map = old_map->Copy(); 1298 MaybeObject* maybe_new_map = old_map->Copy();
1299 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 1299 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1300 1300
1301 new_map->set_is_access_check_needed(false); 1301 new_map->set_is_access_check_needed(false);
1302 object->set_map(new_map); 1302 object->set_map(new_map);
1303 } 1303 }
1304 return isolate->heap()->ToBoolean(needs_access_checks); 1304 return isolate->heap()->ToBoolean(needs_access_checks);
1305 } 1305 }
1306 1306
1307 1307
1308 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) { 1308 RUNTIME_FUNCTION(MaybeObject*, Runtime_EnableAccessChecks) {
1309 ASSERT(args.length() == 1); 1309 ASSERT(args.length() == 1);
1310 CONVERT_ARG_CHECKED(HeapObject, object, 0); 1310 CONVERT_ARG_CHECKED(HeapObject, object, 0);
1311 Map* old_map = object->map(); 1311 Map* old_map = object->map();
1312 if (!old_map->is_access_check_needed()) { 1312 if (!old_map->is_access_check_needed()) {
1313 // Copy map so it won't interfere constructor's initial map. 1313 // Copy map so it won't interfere constructor's initial map.
1314 Map* new_map; 1314 Map* new_map;
1315 MaybeObject* maybe_new_map = old_map->Copy(); 1315 MaybeObject* maybe_new_map = old_map->Copy();
1316 if (!maybe_new_map->To(&new_map)) return maybe_new_map; 1316 if (!maybe_new_map->To(&new_map)) return maybe_new_map;
1317 1317
1318 new_map->set_is_access_check_needed(true); 1318 new_map->set_is_access_check_needed(true);
1319 object->set_map(new_map); 1319 object->set_map(new_map);
1320 } 1320 }
1321 return isolate->heap()->undefined_value(); 1321 return isolate->heap()->undefined_value();
1322 } 1322 }
1323 1323
1324 1324
1325 static Failure* ThrowRedeclarationError(Isolate* isolate, 1325 static Failure* ThrowRedeclarationError(Isolate* isolate,
1326 const char* type, 1326 const char* type,
1327 Handle<String> name) { 1327 Handle<String> name) {
1328 HandleScope scope(isolate); 1328 HandleScope scope(isolate);
1329 Handle<Object> type_handle = 1329 Handle<Object> type_handle =
1330 isolate->factory()->NewStringFromAscii(CStrVector(type)); 1330 isolate->factory()->NewStringFromAscii(CStrVector(type));
1331 Handle<Object> args[2] = { type_handle, name }; 1331 Handle<Object> args[2] = { type_handle, name };
1332 Handle<Object> error = 1332 Handle<Object> error =
1333 isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2)); 1333 isolate->factory()->NewTypeError("redeclaration", HandleVector(args, 2));
1334 return isolate->Throw(*error); 1334 return isolate->Throw(*error);
1335 } 1335 }
1336 1336
1337 1337
1338 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { 1338 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
1339 ASSERT(args.length() == 3); 1339 ASSERT(args.length() == 3);
1340 HandleScope scope(isolate); 1340 HandleScope scope(isolate);
1341 Handle<GlobalObject> global = Handle<GlobalObject>( 1341 Handle<GlobalObject> global = Handle<GlobalObject>(
1342 isolate->context()->global_object()); 1342 isolate->context()->global_object());
1343 1343
1344 Handle<Context> context = args.at<Context>(0); 1344 Handle<Context> context = args.at<Context>(0);
1345 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1); 1345 CONVERT_ARG_HANDLE_CHECKED(FixedArray, pairs, 1);
1346 CONVERT_SMI_ARG_CHECKED(flags, 2); 1346 CONVERT_SMI_ARG_CHECKED(flags, 2);
1347 1347
1348 // Traverse the name/value pairs and set the properties. 1348 // Traverse the name/value pairs and set the properties.
1349 int length = pairs->length(); 1349 int length = pairs->length();
1350 for (int i = 0; i < length; i += 2) { 1350 for (int i = 0; i < length; i += 2) {
1351 HandleScope scope(isolate); 1351 HandleScope scope(isolate);
1352 Handle<String> name(String::cast(pairs->get(i))); 1352 Handle<String> name(String::cast(pairs->get(i)));
1353 Handle<Object> value(pairs->get(i + 1), isolate); 1353 Handle<Object> value(pairs->get(i + 1), isolate);
1354 1354
1355 // We have to declare a global const property. To capture we only 1355 // We have to declare a global const property. To capture we only
1356 // assign to it when evaluating the assignment for "const x = 1356 // assign to it when evaluating the assignment for "const x =
1357 // <expr>" the initial value is the hole. 1357 // <expr>" the initial value is the hole.
1358 bool is_var = value->IsUndefined(); 1358 bool is_var = value->IsUndefined();
1359 bool is_const = value->IsTheHole(); 1359 bool is_const = value->IsTheHole();
1360 bool is_function = value->IsSharedFunctionInfo(); 1360 bool is_function = value->IsSharedFunctionInfo();
1361 bool is_module = value->IsJSModule(); 1361 bool is_module = value->IsJSModule();
1362 ASSERT(is_var + is_const + is_function + is_module == 1); 1362 ASSERT(is_var + is_const + is_function + is_module == 1);
1363 1363
1364 if (is_var || is_const) { 1364 if (is_var || is_const) {
1365 // Lookup the property in the global object, and don't set the 1365 // Lookup the property in the global object, and don't set the
1366 // value of the variable if the property is already there. 1366 // value of the variable if the property is already there.
1367 // Do the lookup locally only, see ES5 erratum. 1367 // Do the lookup locally only, see ES5 erratum.
1368 LookupResult lookup(isolate); 1368 LookupResult lookup(isolate);
1369 if (FLAG_es52_globals) { 1369 if (FLAG_es52_globals) {
1370 Object* obj = *global; 1370 Object* obj = *global;
1371 do { 1371 do {
1372 JSObject::cast(obj)->LocalLookup(*name, &lookup); 1372 JSObject::cast(obj)->LocalLookup(*name, &lookup);
1373 if (lookup.IsFound()) break; 1373 if (lookup.IsFound()) break;
1374 obj = obj->GetPrototype(); 1374 obj = obj->GetPrototype();
1375 } while (obj->IsJSObject() && 1375 } while (obj->IsJSObject() &&
1376 JSObject::cast(obj)->map()->is_hidden_prototype()); 1376 JSObject::cast(obj)->map()->is_hidden_prototype());
1377 } else { 1377 } else {
1378 global->Lookup(*name, &lookup); 1378 global->Lookup(*name, &lookup);
1379 } 1379 }
1380 if (lookup.IsFound()) { 1380 if (lookup.IsFound()) {
1381 // We found an existing property. Unless it was an interceptor 1381 // We found an existing property. Unless it was an interceptor
1382 // that claims the property is absent, skip this declaration. 1382 // that claims the property is absent, skip this declaration.
1383 if (!lookup.IsInterceptor()) continue; 1383 if (!lookup.IsInterceptor()) continue;
1384 PropertyAttributes attributes = global->GetPropertyAttribute(*name); 1384 PropertyAttributes attributes = global->GetPropertyAttribute(*name);
1385 if (attributes != ABSENT) continue; 1385 if (attributes != ABSENT) continue;
1386 // Fall-through and introduce the absent property by using 1386 // Fall-through and introduce the absent property by using
1387 // SetProperty. 1387 // SetProperty.
1388 } 1388 }
1389 } else if (is_function) { 1389 } else if (is_function) {
1390 // Copy the function and update its context. Use it as value. 1390 // Copy the function and update its context. Use it as value.
1391 Handle<SharedFunctionInfo> shared = 1391 Handle<SharedFunctionInfo> shared =
1392 Handle<SharedFunctionInfo>::cast(value); 1392 Handle<SharedFunctionInfo>::cast(value);
1393 Handle<JSFunction> function = 1393 Handle<JSFunction> function =
1394 isolate->factory()->NewFunctionFromSharedFunctionInfo( 1394 isolate->factory()->NewFunctionFromSharedFunctionInfo(
1395 shared, context, TENURED); 1395 shared, context, TENURED);
1396 value = function; 1396 value = function;
1397 } 1397 }
1398 1398
1399 LookupResult lookup(isolate); 1399 LookupResult lookup(isolate);
1400 global->LocalLookup(*name, &lookup); 1400 global->LocalLookup(*name, &lookup);
1401 1401
1402 // Compute the property attributes. According to ECMA-262, 1402 // Compute the property attributes. According to ECMA-262,
1403 // the property must be non-configurable except in eval. 1403 // the property must be non-configurable except in eval.
1404 int attr = NONE; 1404 int attr = NONE;
1405 bool is_eval = DeclareGlobalsEvalFlag::decode(flags); 1405 bool is_eval = DeclareGlobalsEvalFlag::decode(flags);
1406 if (!is_eval || is_module) { 1406 if (!is_eval || is_module) {
1407 attr |= DONT_DELETE; 1407 attr |= DONT_DELETE;
1408 } 1408 }
1409 bool is_native = DeclareGlobalsNativeFlag::decode(flags); 1409 bool is_native = DeclareGlobalsNativeFlag::decode(flags);
1410 if (is_const || is_module || (is_native && is_function)) { 1410 if (is_const || is_module || (is_native && is_function)) {
1411 attr |= READ_ONLY; 1411 attr |= READ_ONLY;
1412 } 1412 }
1413 1413
1414 LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags); 1414 LanguageMode language_mode = DeclareGlobalsLanguageMode::decode(flags);
1415 1415
1416 if (!lookup.IsFound() || is_function || is_module) { 1416 if (!lookup.IsFound() || is_function || is_module) {
1417 // If the local property exists, check that we can reconfigure it 1417 // If the local property exists, check that we can reconfigure it
1418 // as required for function declarations. 1418 // as required for function declarations.
1419 if (lookup.IsFound() && lookup.IsDontDelete()) { 1419 if (lookup.IsFound() && lookup.IsDontDelete()) {
1420 if (lookup.IsReadOnly() || lookup.IsDontEnum() || 1420 if (lookup.IsReadOnly() || lookup.IsDontEnum() ||
1421 lookup.IsPropertyCallbacks()) { 1421 lookup.IsPropertyCallbacks()) {
1422 return ThrowRedeclarationError( 1422 return ThrowRedeclarationError(
1423 isolate, is_function ? "function" : "module", name); 1423 isolate, is_function ? "function" : "module", name);
1424 } 1424 }
1425 // If the existing property is not configurable, keep its attributes. 1425 // If the existing property is not configurable, keep its attributes.
1426 attr = lookup.GetAttributes(); 1426 attr = lookup.GetAttributes();
1427 } 1427 }
1428 // Define or redefine own property. 1428 // Define or redefine own property.
1429 RETURN_IF_EMPTY_HANDLE(isolate, 1429 RETURN_IF_EMPTY_HANDLE(isolate,
1430 JSObject::SetLocalPropertyIgnoreAttributes( 1430 JSObject::SetLocalPropertyIgnoreAttributes(
1431 global, name, value, static_cast<PropertyAttributes>(attr))); 1431 global, name, value, static_cast<PropertyAttributes>(attr)));
1432 } else { 1432 } else {
1433 // Do a [[Put]] on the existing (own) property. 1433 // Do a [[Put]] on the existing (own) property.
1434 RETURN_IF_EMPTY_HANDLE(isolate, 1434 RETURN_IF_EMPTY_HANDLE(isolate,
1435 JSObject::SetProperty( 1435 JSObject::SetProperty(
1436 global, name, value, static_cast<PropertyAttributes>(attr), 1436 global, name, value, static_cast<PropertyAttributes>(attr),
1437 language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode)); 1437 language_mode == CLASSIC_MODE ? kNonStrictMode : kStrictMode));
1438 } 1438 }
1439 } 1439 }
1440 1440
1441 ASSERT(!isolate->has_pending_exception()); 1441 ASSERT(!isolate->has_pending_exception());
1442 return isolate->heap()->undefined_value(); 1442 return isolate->heap()->undefined_value();
1443 } 1443 }
1444 1444
1445 1445
1446 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) { 1446 RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareContextSlot) {
1447 HandleScope scope(isolate); 1447 HandleScope scope(isolate);
1448 ASSERT(args.length() == 4); 1448 ASSERT(args.length() == 4);
1449 1449
1450 // Declarations are always made in a function or native context. In the 1450 // Declarations are always made in a function or native context. In the
1451 // case of eval code, the context passed is the context of the caller, 1451 // case of eval code, the context passed is the context of the caller,
1452 // which may be some nested context and not the declaration context. 1452 // which may be some nested context and not the declaration context.
1453 RUNTIME_ASSERT(args[0]->IsContext()); 1453 RUNTIME_ASSERT(args[0]->IsContext());
1454 Handle<Context> context(Context::cast(args[0])->declaration_context()); 1454 Handle<Context> context(Context::cast(args[0])->declaration_context());
1455 1455
1456 Handle<String> name(String::cast(args[1])); 1456 Handle<String> name(String::cast(args[1]));
1457 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2)); 1457 PropertyAttributes mode = static_cast<PropertyAttributes>(args.smi_at(2));
1458 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE); 1458 RUNTIME_ASSERT(mode == READ_ONLY || mode == NONE);
1459 Handle<Object> initial_value(args[3], isolate); 1459 Handle<Object> initial_value(args[3], isolate);
1460 1460
1461 int index; 1461 int index;
1462 PropertyAttributes attributes; 1462 PropertyAttributes attributes;
1463 ContextLookupFlags flags = DONT_FOLLOW_CHAINS; 1463 ContextLookupFlags flags = DONT_FOLLOW_CHAINS;
1464 BindingFlags binding_flags; 1464 BindingFlags binding_flags;
1465 Handle<Object> holder = 1465 Handle<Object> holder =
1466 context->Lookup(name, flags, &index, &attributes, &binding_flags); 1466 context->Lookup(name, flags, &index, &attributes, &binding_flags);
1467 1467
1468 if (attributes != ABSENT) { 1468 if (attributes != ABSENT) {
1469 // The name was declared before; check for conflicting re-declarations. 1469 // The name was declared before; check for conflicting re-declarations.
1470 // Note: this is actually inconsistent with what happens for globals (where 1470 // Note: this is actually inconsistent with what happens for globals (where
1471 // we silently ignore such declarations). 1471 // we silently ignore such declarations).
1472 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) { 1472 if (((attributes & READ_ONLY) != 0) || (mode == READ_ONLY)) {
1473 // Functions are not read-only. 1473 // Functions are not read-only.
1474 ASSERT(mode != READ_ONLY || initial_value->IsTheHole()); 1474 ASSERT(mode != READ_ONLY || initial_value->IsTheHole());
1475 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var"; 1475 const char* type = ((attributes & READ_ONLY) != 0) ? "const" : "var";
1476 return ThrowRedeclarationError(isolate, type, name); 1476 return ThrowRedeclarationError(isolate, type, name);
1477 } 1477 }
1478 1478
1479 // Initialize it if necessary. 1479 // Initialize it if necessary.
1480 if (*initial_value != NULL) { 1480 if (*initial_value != NULL) {
1481 if (index >= 0) { 1481 if (index >= 0) {
1482 ASSERT(holder.is_identical_to(context)); 1482 ASSERT(holder.is_identical_to(context));
1483 if (((attributes & READ_ONLY) == 0) || 1483 if (((attributes & READ_ONLY) == 0) ||
1484 context->get(index)->IsTheHole()) { 1484 context->get(index)->IsTheHole()) {
1485 context->set(index, *initial_value); 1485 context->set(index, *initial_value);
1486 } 1486 }
1487 } else { 1487 } else {
1488 // Slow case: The property is in the context extension object of a 1488 // Slow case: The property is in the context extension object of a
1489 // function context or the global object of a native context. 1489 // function context or the global object of a native context.
1490 Handle<JSObject> object = Handle<JSObject>::cast(holder); 1490 Handle<JSObject> object = Handle<JSObject>::cast(holder);
1491 RETURN_IF_EMPTY_HANDLE( 1491 RETURN_IF_EMPTY_HANDLE(
1492 isolate, 1492 isolate,
1493 JSReceiver::SetProperty(object, name, initial_value, mode, 1493 JSReceiver::SetProperty(object, name, initial_value, mode,
1494 kNonStrictMode)); 1494 kNonStrictMode));
1495 } 1495 }
1496 } 1496 }
1497 1497
1498 } else { 1498 } else {
1499 // The property is not in the function context. It needs to be 1499 // The property is not in the function context. It needs to be
1500 // "declared" in the function context's extension context or as a 1500 // "declared" in the function context's extension context or as a
1501 // property of the the global object. 1501 // property of the the global object.
1502 Handle<JSObject> object; 1502 Handle<JSObject> object;
1503 if (context->has_extension()) { 1503 if (context->has_extension()) {
1504 object = Handle<JSObject>(JSObject::cast(context->extension())); 1504 object = Handle<JSObject>(JSObject::cast(context->extension()));
1505 } else { 1505 } else {
1506 // Context extension objects are allocated lazily. 1506 // Context extension objects are allocated lazily.
1507 ASSERT(context->IsFunctionContext()); 1507 ASSERT(context->IsFunctionContext());
1508 object = isolate->factory()->NewJSObject( 1508 object = isolate->factory()->NewJSObject(
1509 isolate->context_extension_function()); 1509 isolate->context_extension_function());
1510 context->set_extension(*object); 1510 context->set_extension(*object);
1511 } 1511 }
1512 ASSERT(*object != NULL); 1512 ASSERT(*object != NULL);
1513 1513
1514 // Declare the property by setting it to the initial value if provided, 1514 // Declare the property by setting it to the initial value if provided,
1515 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for 1515 // or undefined, and use the correct mode (e.g. READ_ONLY attribute for
1516 // constant declarations). 1516 // constant declarations).
1517 ASSERT(!object->HasLocalProperty(*name)); 1517 ASSERT(!object->HasLocalProperty(*name));
1518 Handle<Object> value(isolate->heap()->undefined_value(), isolate); 1518 Handle<Object> value(isolate->heap()->undefined_value(), isolate);
1519 if (*initial_value != NULL) value = initial_value; 1519 if (*initial_value != NULL) value = initial_value;
1520 // Declaring a const context slot is a conflicting declaration if 1520 // Declaring a const context slot is a conflicting declaration if
1521 // there is a callback with that name in a prototype. It is 1521 // there is a callback with that name in a prototype. It is
1522 // allowed to introduce const variables in 1522 // allowed to introduce const variables in
1523 // JSContextExtensionObjects. They are treated specially in 1523 // JSContextExtensionObjects. They are treated specially in
1524 // SetProperty and no setters are invoked for those since they are 1524 // SetProperty and no setters are invoked for those since they are
1525 // not real JSObjects. 1525 // not real JSObjects.
1526 if (initial_value->IsTheHole() && 1526 if (initial_value->IsTheHole() &&
1527 !object->IsJSContextExtensionObject()) { 1527 !object->IsJSContextExtensionObject()) {
1528 LookupResult lookup(isolate); 1528 LookupResult lookup(isolate);
1529 object->Lookup(*name, &lookup); 1529 object->Lookup(*name, &lookup);
1530 if (lookup.IsPropertyCallbacks()) { 1530 if (lookup.IsPropertyCallbacks()) {
1531 return ThrowRedeclarationError(isolate, "const", name); 1531 return ThrowRedeclarationError(isolate, "const", name);
1532 } 1532 }
1533 } 1533 }
1534 if (object->IsJSGlobalObject()) { 1534 if (object->IsJSGlobalObject()) {
1535 // Define own property on the global object. 1535 // Define own property on the global object.
1536 RETURN_IF_EMPTY_HANDLE(isolate, 1536 RETURN_IF_EMPTY_HANDLE(isolate,
1537 JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode)); 1537 JSObject::SetLocalPropertyIgnoreAttributes(object, name, value, mode));
1538 } else { 1538 } else {
1539 RETURN_IF_EMPTY_HANDLE(isolate, 1539 RETURN_IF_EMPTY_HANDLE(isolate,
1540 JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode)); 1540 JSReceiver::SetProperty(object, name, value, mode, kNonStrictMode));
1541 } 1541 }
1542 } 1542 }
1543 1543
1544 return isolate->heap()->undefined_value(); 1544 return isolate->heap()->undefined_value();
1545 } 1545 }
1546 1546
1547 1547
1548 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { 1548 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
1549 NoHandleAllocation nha; 1549 NoHandleAllocation nha;
1550 // args[0] == name 1550 // args[0] == name
1551 // args[1] == language_mode 1551 // args[1] == language_mode
1552 // args[2] == value (optional) 1552 // args[2] == value (optional)
1553 1553
1554 // Determine if we need to assign to the variable if it already 1554 // Determine if we need to assign to the variable if it already
1555 // exists (based on the number of arguments). 1555 // exists (based on the number of arguments).
1556 RUNTIME_ASSERT(args.length() == 2 || args.length() == 3); 1556 RUNTIME_ASSERT(args.length() == 2 || args.length() == 3);
1557 bool assign = args.length() == 3; 1557 bool assign = args.length() == 3;
1558 1558
1559 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 1559 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1560 GlobalObject* global = isolate->context()->global_object(); 1560 GlobalObject* global = isolate->context()->global_object();
1561 RUNTIME_ASSERT(args[1]->IsSmi()); 1561 RUNTIME_ASSERT(args[1]->IsSmi());
1562 CONVERT_LANGUAGE_MODE_ARG(language_mode, 1); 1562 CONVERT_LANGUAGE_MODE_ARG(language_mode, 1);
1563 StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE) 1563 StrictModeFlag strict_mode_flag = (language_mode == CLASSIC_MODE)
1564 ? kNonStrictMode : kStrictMode; 1564 ? kNonStrictMode : kStrictMode;
1565 1565
1566 // According to ECMA-262, section 12.2, page 62, the property must 1566 // According to ECMA-262, section 12.2, page 62, the property must
1567 // not be deletable. 1567 // not be deletable.
1568 PropertyAttributes attributes = DONT_DELETE; 1568 PropertyAttributes attributes = DONT_DELETE;
1569 1569
1570 // Lookup the property locally in the global object. If it isn't 1570 // Lookup the property locally in the global object. If it isn't
1571 // there, there is a property with this name in the prototype chain. 1571 // there, there is a property with this name in the prototype chain.
1572 // We follow Safari and Firefox behavior and only set the property 1572 // We follow Safari and Firefox behavior and only set the property
1573 // locally if there is an explicit initialization value that we have 1573 // locally if there is an explicit initialization value that we have
1574 // to assign to the property. 1574 // to assign to the property.
1575 // Note that objects can have hidden prototypes, so we need to traverse 1575 // Note that objects can have hidden prototypes, so we need to traverse
1576 // the whole chain of hidden prototypes to do a 'local' lookup. 1576 // the whole chain of hidden prototypes to do a 'local' lookup.
1577 Object* object = global; 1577 Object* object = global;
1578 LookupResult lookup(isolate); 1578 LookupResult lookup(isolate);
1579 while (object->IsJSObject() && 1579 while (object->IsJSObject() &&
1580 JSObject::cast(object)->map()->is_hidden_prototype()) { 1580 JSObject::cast(object)->map()->is_hidden_prototype()) {
1581 JSObject* raw_holder = JSObject::cast(object); 1581 JSObject* raw_holder = JSObject::cast(object);
1582 raw_holder->LocalLookup(*name, &lookup); 1582 raw_holder->LocalLookup(*name, &lookup);
1583 if (lookup.IsInterceptor()) { 1583 if (lookup.IsInterceptor()) {
1584 HandleScope handle_scope(isolate); 1584 HandleScope handle_scope(isolate);
1585 Handle<JSObject> holder(raw_holder); 1585 Handle<JSObject> holder(raw_holder);
1586 PropertyAttributes intercepted = holder->GetPropertyAttribute(*name); 1586 PropertyAttributes intercepted = holder->GetPropertyAttribute(*name);
1587 // Update the raw pointer in case it's changed due to GC. 1587 // Update the raw pointer in case it's changed due to GC.
1588 raw_holder = *holder; 1588 raw_holder = *holder;
1589 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) { 1589 if (intercepted != ABSENT && (intercepted & READ_ONLY) == 0) {
1590 // Found an interceptor that's not read only. 1590 // Found an interceptor that's not read only.
1591 if (assign) { 1591 if (assign) {
1592 return raw_holder->SetProperty( 1592 return raw_holder->SetProperty(
1593 &lookup, *name, args[2], attributes, strict_mode_flag); 1593 &lookup, *name, args[2], attributes, strict_mode_flag);
1594 } else { 1594 } else {
1595 return isolate->heap()->undefined_value(); 1595 return isolate->heap()->undefined_value();
1596 } 1596 }
1597 } 1597 }
1598 } 1598 }
1599 object = raw_holder->GetPrototype(); 1599 object = raw_holder->GetPrototype();
1600 } 1600 }
1601 1601
1602 // Reload global in case the loop above performed a GC. 1602 // Reload global in case the loop above performed a GC.
1603 global = isolate->context()->global_object(); 1603 global = isolate->context()->global_object();
1604 if (assign) { 1604 if (assign) {
1605 return global->SetProperty(*name, args[2], attributes, strict_mode_flag); 1605 return global->SetProperty(*name, args[2], attributes, strict_mode_flag);
1606 } 1606 }
1607 return isolate->heap()->undefined_value(); 1607 return isolate->heap()->undefined_value();
1608 } 1608 }
1609 1609
1610 1610
1611 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { 1611 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) {
1612 // All constants are declared with an initial value. The name 1612 // All constants are declared with an initial value. The name
1613 // of the constant is the first argument and the initial value 1613 // of the constant is the first argument and the initial value
1614 // is the second. 1614 // is the second.
1615 RUNTIME_ASSERT(args.length() == 2); 1615 RUNTIME_ASSERT(args.length() == 2);
1616 CONVERT_ARG_HANDLE_CHECKED(String, name, 0); 1616 CONVERT_ARG_HANDLE_CHECKED(String, name, 0);
1617 Handle<Object> value = args.at<Object>(1); 1617 Handle<Object> value = args.at<Object>(1);
1618 1618
1619 // Get the current global object from top. 1619 // Get the current global object from top.
1620 GlobalObject* global = isolate->context()->global_object(); 1620 GlobalObject* global = isolate->context()->global_object();
1621 1621
1622 // According to ECMA-262, section 12.2, page 62, the property must 1622 // According to ECMA-262, section 12.2, page 62, the property must
1623 // not be deletable. Since it's a const, it must be READ_ONLY too. 1623 // not be deletable. Since it's a const, it must be READ_ONLY too.
1624 PropertyAttributes attributes = 1624 PropertyAttributes attributes =
1625 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY); 1625 static_cast<PropertyAttributes>(DONT_DELETE | READ_ONLY);
1626 1626
1627 // Lookup the property locally in the global object. If it isn't 1627 // Lookup the property locally in the global object. If it isn't
1628 // there, we add the property and take special precautions to always 1628 // there, we add the property and take special precautions to always
1629 // add it as a local property even in case of callbacks in the 1629 // add it as a local property even in case of callbacks in the
1630 // prototype chain (this rules out using SetProperty). 1630 // prototype chain (this rules out using SetProperty).
1631 // We use SetLocalPropertyIgnoreAttributes instead 1631 // We use SetLocalPropertyIgnoreAttributes instead
1632 LookupResult lookup(isolate); 1632 LookupResult lookup(isolate);
1633 global->LocalLookup(*name, &lookup); 1633 global->LocalLookup(*name, &lookup);
1634 if (!lookup.IsFound()) { 1634 if (!lookup.IsFound()) {
1635 return global->SetLocalPropertyIgnoreAttributes(*name, 1635 return global->SetLocalPropertyIgnoreAttributes(*name,
1636 *value, 1636 *value,
1637 attributes); 1637 attributes);
1638 } 1638 }
1639 1639
1640 if (!lookup.IsReadOnly()) { 1640 if (!lookup.IsReadOnly()) {
1641 // Restore global object from context (in case of GC) and continue 1641 // Restore global object from context (in case of GC) and continue
1642 // with setting the value. 1642 // with setting the value.
1643 HandleScope handle_scope(isolate); 1643 HandleScope handle_scope(isolate);
1644 Handle<GlobalObject> global(isolate->context()->global_object()); 1644 Handle<GlobalObject> global(isolate->context()->global_object());
1645 1645
1646 // BUG 1213575: Handle the case where we have to set a read-only 1646 // BUG 1213575: Handle the case where we have to set a read-only
1647 // property through an interceptor and only do it if it's 1647 // property through an interceptor and only do it if it's
1648 // uninitialized, e.g. the hole. Nirk... 1648 // uninitialized, e.g. the hole. Nirk...
1649 // Passing non-strict mode because the property is writable. 1649 // Passing non-strict mode because the property is writable.
1650 RETURN_IF_EMPTY_HANDLE( 1650 RETURN_IF_EMPTY_HANDLE(
1651 isolate, 1651 isolate,
1652 JSReceiver::SetProperty(global, name, value, attributes, 1652 JSReceiver::SetProperty(global, name, value, attributes,
1653 kNonStrictMode)); 1653 kNonStrictMode));
1654 return *value; 1654 return *value;
1655 } 1655 }
1656 1656
1657 // Set the value, but only if we're assigning the initial value to a 1657 // Set the value, but only if we're assigning the initial value to a
1658 // constant. For now, we determine this by checking if the 1658 // constant. For now, we determine this by checking if the
1659 // current value is the hole. 1659 // current value is the hole.
1660 // Strict mode handling not needed (const is disallowed in strict mode). 1660 // Strict mode handling not needed (const is disallowed in strict mode).
1661 if (lookup.IsField()) { 1661 if (lookup.IsField()) {
1662 FixedArray* properties = global->properties(); 1662 FixedArray* properties = global->properties();
1663 int index = lookup.GetFieldIndex(); 1663 int index = lookup.GetFieldIndex();
1664 if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) { 1664 if (properties->get(index)->IsTheHole() || !lookup.IsReadOnly()) {
1665 properties->set(index, *value); 1665 properties->set(index, *value);
1666 } 1666 }
1667 } else if (lookup.IsNormal()) { 1667 } else if (lookup.IsNormal()) {
1668 if (global->GetNormalizedProperty(&lookup)->IsTheHole() || 1668 if (global->GetNormalizedProperty(&lookup)->IsTheHole() ||
1669 !lookup.IsReadOnly()) { 1669 !lookup.IsReadOnly()) {
1670 global->SetNormalizedProperty(&lookup, *value); 1670 global->SetNormalizedProperty(&lookup, *value);
1671 } 1671 }
1672 } else { 1672 } else {
1673 // Ignore re-initialization of constants that have already been 1673 // Ignore re-initialization of constants that have already been
1674 // assigned a function value. 1674 // assigned a function value.
1675 ASSERT(lookup.IsReadOnly() && lookup.IsConstantFunction()); 1675 ASSERT(lookup.IsReadOnly() && lookup.IsConstantFunction());
1676 } 1676 }
1677 1677
1678 // Use the set value as the result of the operation. 1678 // Use the set value as the result of the operation.
1679 return *value; 1679 return *value;
1680 } 1680 }
1681 1681
1682 1682
1683 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) { 1683 RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstContextSlot) {
1684 HandleScope scope(isolate); 1684 HandleScope scope(isolate);
1685 ASSERT(args.length() == 3); 1685 ASSERT(args.length() == 3);
1686 1686
1687 Handle<Object> value(args[0], isolate); 1687 Handle<Object> value(args[0], isolate);
1688 ASSERT(!value->IsTheHole()); 1688 ASSERT(!value->IsTheHole());
1689 1689
1690 // Initializations are always done in a function or native context. 1690 // Initializations are always done in a function or native context.
1691 RUNTIME_ASSERT(args[1]->IsContext()); 1691 RUNTIME_ASSERT(args[1]->IsContext());
1692 Handle<Context> context(Context::cast(args[1])->declaration_context()); 1692 Handle<Context> context(Context::cast(args[1])->declaration_context());
1693 1693
1694 Handle<String> name(String::cast(args[2])); 1694 Handle<String> name(String::cast(args[2]));
1695 1695
1696 int index; 1696 int index;
1697 PropertyAttributes attributes; 1697 PropertyAttributes attributes;
1698 ContextLookupFlags flags = FOLLOW_CHAINS; 1698 ContextLookupFlags flags = FOLLOW_CHAINS;
1699 BindingFlags binding_flags; 1699 BindingFlags binding_flags;
1700 Handle<Object> holder = 1700 Handle<Object> holder =
1701 context->Lookup(name, flags, &index, &attributes, &binding_flags); 1701 context->Lookup(name, flags, &index, &attributes, &binding_flags);
1702 1702
1703 if (index >= 0) { 1703 if (index >= 0) {
1704 ASSERT(holder->IsContext()); 1704 ASSERT(holder->IsContext());
1705 // Property was found in a context. Perform the assignment if we 1705 // Property was found in a context. Perform the assignment if we
1706 // found some non-constant or an uninitialized constant. 1706 // found some non-constant or an uninitialized constant.
1707 Handle<Context> context = Handle<Context>::cast(holder); 1707 Handle<Context> context = Handle<Context>::cast(holder);
1708 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) { 1708 if ((attributes & READ_ONLY) == 0 || context->get(index)->IsTheHole()) {
1709 context->set(index, *value); 1709 context->set(index, *value);
1710 } 1710 }
1711 return *value; 1711 return *value;
1712 } 1712 }
1713 1713
1714 // The property could not be found, we introduce it as a property of the 1714 // The property could not be found, we introduce it as a property of the
1715 // global object. 1715 // global object.
1716 if (attributes == ABSENT) { 1716 if (attributes == ABSENT) {
1717 Handle<JSObject> global = Handle<JSObject>( 1717 Handle<JSObject> global = Handle<JSObject>(
1718 isolate->context()->global_object()); 1718 isolate->context()->global_object());
1719 // Strict mode not needed (const disallowed in strict mode). 1719 // Strict mode not needed (const disallowed in strict mode).
1720 RETURN_IF_EMPTY_HANDLE( 1720 RETURN_IF_EMPTY_HANDLE(
1721 isolate, 1721 isolate,
1722 JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode)); 1722 JSReceiver::SetProperty(global, name, value, NONE, kNonStrictMode));
1723 return *value; 1723 return *value;
1724 } 1724 }
1725 1725
1726 // The property was present in some function's context extension object, 1726 // The property was present in some function's context extension object,
1727 // as a property on the subject of a with, or as a property of the global 1727 // as a property on the subject of a with, or as a property of the global
1728 // object. 1728 // object.
1729 // 1729 //
1730 // In most situations, eval-introduced consts should still be present in 1730 // In most situations, eval-introduced consts should still be present in
1731 // the context extension object. However, because declaration and 1731 // the context extension object. However, because declaration and
1732 // initialization are separate, the property might have been deleted 1732 // initialization are separate, the property might have been deleted
1733 // before we reach the initialization point. 1733 // before we reach the initialization point.
1734 // 1734 //
1735 // Example: 1735 // Example:
1736 // 1736 //
1737 // function f() { eval("delete x; const x;"); } 1737 // function f() { eval("delete x; const x;"); }
1738 // 1738 //
1739 // In that case, the initialization behaves like a normal assignment. 1739 // In that case, the initialization behaves like a normal assignment.
1740 Handle<JSObject> object = Handle<JSObject>::cast(holder); 1740 Handle<JSObject> object = Handle<JSObject>::cast(holder);
1741 1741
1742 if (*object == context->extension()) { 1742 if (*object == context->extension()) {
1743 // This is the property that was introduced by the const declaration. 1743 // This is the property that was introduced by the const declaration.
1744 // Set it if it hasn't been set before. NOTE: We cannot use 1744 // Set it if it hasn't been set before. NOTE: We cannot use
1745 // GetProperty() to get the current value as it 'unholes' the value. 1745 // GetProperty() to get the current value as it 'unholes' the value.
1746 LookupResult lookup(isolate); 1746 LookupResult lookup(isolate);
1747 object->LocalLookupRealNamedProperty(*name, &lookup); 1747 object->LocalLookupRealNamedProperty(*name, &lookup);
1748 ASSERT(lookup.IsFound()); // the property was declared 1748 ASSERT(lookup.IsFound()); // the property was declared
1749 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only 1749 ASSERT(lookup.IsReadOnly()); // and it was declared as read-only
1750 1750
1751 if (lookup.IsField()) { 1751 if (lookup.IsField()) {
1752 FixedArray* properties = object->properties(); 1752 FixedArray* properties = object->properties();
1753 int index = lookup.GetFieldIndex(); 1753 int index = lookup.GetFieldIndex();
1754 if (properties->get(index)->IsTheHole()) { 1754 if (properties->get(index)->IsTheHole()) {
1755 properties->set(index, *value); 1755 properties->set(index, *value);
1756 } 1756 }
1757 } else if (lookup.IsNormal()) { 1757 } else if (lookup.IsNormal()) {
1758 if (object->GetNormalizedProperty(&lookup)->IsTheHole()) { 1758 if (object->GetNormalizedProperty(&lookup)->IsTheHole()) {
1759 object->SetNormalizedProperty(&lookup, *value); 1759 object->SetNormalizedProperty(&lookup, *value);
1760 } 1760 }
1761 } else { 1761 } else {
1762 // We should not reach here. Any real, named property should be 1762 // We should not reach here. Any real, named property should be
1763 // either a field or a dictionary slot. 1763 // either a field or a dictionary slot.
1764 UNREACHABLE(); 1764 UNREACHABLE();
1765 } 1765 }
1766 } else { 1766 } else {
1767 // The property was found on some other object. Set it if it is not a 1767 // The property was found on some other object. Set it if it is not a
1768 // read-only property. 1768 // read-only property.
1769 if ((attributes & READ_ONLY) == 0) { 1769 if ((attributes & READ_ONLY) == 0) {
1770 // Strict mode not needed (const disallowed in strict mode). 1770 // Strict mode not needed (const disallowed in strict mode).
1771 RETURN_IF_EMPTY_HANDLE( 1771 RETURN_IF_EMPTY_HANDLE(
1772 isolate, 1772 isolate,
1773 JSReceiver::SetProperty(object, name, value, attributes, 1773 JSReceiver::SetProperty(object, name, value, attributes,
1774 kNonStrictMode)); 1774 kNonStrictMode));
1775 } 1775 }
1776 } 1776 }
1777 1777
1778 return *value; 1778 return *value;
1779 } 1779 }
1780 1780
1781 1781
1782 RUNTIME_FUNCTION(MaybeObject*, 1782 RUNTIME_FUNCTION(MaybeObject*,
1783 Runtime_OptimizeObjectForAddingMultipleProperties) { 1783 Runtime_OptimizeObjectForAddingMultipleProperties) {
1784 HandleScope scope(isolate); 1784 HandleScope scope(isolate);
1785 ASSERT(args.length() == 2); 1785 ASSERT(args.length() == 2);
1786 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0); 1786 CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
1787 CONVERT_SMI_ARG_CHECKED(properties, 1); 1787 CONVERT_SMI_ARG_CHECKED(properties, 1);
1788 if (object->HasFastProperties()) { 1788 if (object->HasFastProperties()) {
1789 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties); 1789 JSObject::NormalizeProperties(object, KEEP_INOBJECT_PROPERTIES, properties);
1790 } 1790 }
1791 return *object; 1791 return *object;
1792 } 1792 }
1793 1793
1794 1794
1795 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) { 1795 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExec) {
1796 HandleScope scope(isolate); 1796 HandleScope scope(isolate);
1797 ASSERT(args.length() == 4); 1797 ASSERT(args.length() == 4);
1798 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); 1798 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
1799 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); 1799 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
1800 // Due to the way the JS calls are constructed this must be less than the 1800 // Due to the way the JS calls are constructed this must be less than the
1801 // length of a string, i.e. it is always a Smi. We check anyway for security. 1801 // length of a string, i.e. it is always a Smi. We check anyway for security.
1802 CONVERT_SMI_ARG_CHECKED(index, 2); 1802 CONVERT_SMI_ARG_CHECKED(index, 2);
1803 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3); 1803 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
1804 RUNTIME_ASSERT(last_match_info->HasFastObjectElements()); 1804 RUNTIME_ASSERT(last_match_info->HasFastObjectElements());
1805 RUNTIME_ASSERT(index >= 0); 1805 RUNTIME_ASSERT(index >= 0);
1806 RUNTIME_ASSERT(index <= subject->length()); 1806 RUNTIME_ASSERT(index <= subject->length());
1807 isolate->counters()->regexp_entry_runtime()->Increment(); 1807 isolate->counters()->regexp_entry_runtime()->Increment();
1808 Handle<Object> result = RegExpImpl::Exec(regexp, 1808 Handle<Object> result = RegExpImpl::Exec(regexp,
1809 subject, 1809 subject,
1810 index, 1810 index,
1811 last_match_info); 1811 last_match_info);
1812 if (result.is_null()) return Failure::Exception(); 1812 if (result.is_null()) return Failure::Exception();
1813 return *result; 1813 return *result;
1814 } 1814 }
1815 1815
1816 1816
1817 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) { 1817 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpConstructResult) {
1818 ASSERT(args.length() == 3); 1818 ASSERT(args.length() == 3);
1819 CONVERT_SMI_ARG_CHECKED(elements_count, 0); 1819 CONVERT_SMI_ARG_CHECKED(elements_count, 0);
1820 if (elements_count < 0 || 1820 if (elements_count < 0 ||
1821 elements_count > FixedArray::kMaxLength || 1821 elements_count > FixedArray::kMaxLength ||
1822 !Smi::IsValid(elements_count)) { 1822 !Smi::IsValid(elements_count)) {
1823 return isolate->ThrowIllegalOperation(); 1823 return isolate->ThrowIllegalOperation();
1824 } 1824 }
1825 Object* new_object; 1825 Object* new_object;
1826 { MaybeObject* maybe_new_object = 1826 { MaybeObject* maybe_new_object =
1827 isolate->heap()->AllocateFixedArrayWithHoles(elements_count); 1827 isolate->heap()->AllocateFixedArrayWithHoles(elements_count);
1828 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; 1828 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1829 } 1829 }
1830 FixedArray* elements = FixedArray::cast(new_object); 1830 FixedArray* elements = FixedArray::cast(new_object);
1831 { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw( 1831 { MaybeObject* maybe_new_object = isolate->heap()->AllocateRaw(
1832 JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE); 1832 JSRegExpResult::kSize, NEW_SPACE, OLD_POINTER_SPACE);
1833 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object; 1833 if (!maybe_new_object->ToObject(&new_object)) return maybe_new_object;
1834 } 1834 }
1835 { 1835 {
1836 AssertNoAllocation no_gc; 1836 AssertNoAllocation no_gc;
1837 HandleScope scope(isolate); 1837 HandleScope scope(isolate);
1838 reinterpret_cast<HeapObject*>(new_object)-> 1838 reinterpret_cast<HeapObject*>(new_object)->
1839 set_map(isolate->native_context()->regexp_result_map()); 1839 set_map(isolate->native_context()->regexp_result_map());
1840 } 1840 }
1841 JSArray* array = JSArray::cast(new_object); 1841 JSArray* array = JSArray::cast(new_object);
1842 array->set_properties(isolate->heap()->empty_fixed_array()); 1842 array->set_properties(isolate->heap()->empty_fixed_array());
1843 array->set_elements(elements); 1843 array->set_elements(elements);
1844 array->set_length(Smi::FromInt(elements_count)); 1844 array->set_length(Smi::FromInt(elements_count));
1845 // Write in-object properties after the length of the array. 1845 // Write in-object properties after the length of the array.
1846 array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]); 1846 array->InObjectPropertyAtPut(JSRegExpResult::kIndexIndex, args[1]);
1847 array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]); 1847 array->InObjectPropertyAtPut(JSRegExpResult::kInputIndex, args[2]);
1848 return array; 1848 return array;
1849 } 1849 }
1850 1850
1851 1851
1852 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) { 1852 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpInitializeObject) {
1853 AssertNoAllocation no_alloc; 1853 AssertNoAllocation no_alloc;
1854 ASSERT(args.length() == 5); 1854 ASSERT(args.length() == 5);
1855 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0); 1855 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
1856 CONVERT_ARG_CHECKED(String, source, 1); 1856 CONVERT_ARG_CHECKED(String, source, 1);
1857 // If source is the empty string we set it to "(?:)" instead as 1857 // If source is the empty string we set it to "(?:)" instead as
1858 // suggested by ECMA-262, 5th, section 15.10.4.1. 1858 // suggested by ECMA-262, 5th, section 15.10.4.1.
1859 if (source->length() == 0) source = isolate->heap()->query_colon_symbol(); 1859 if (source->length() == 0) source = isolate->heap()->query_colon_symbol();
1860 1860
1861 Object* global = args[2]; 1861 Object* global = args[2];
1862 if (!global->IsTrue()) global = isolate->heap()->false_value(); 1862 if (!global->IsTrue()) global = isolate->heap()->false_value();
1863 1863
1864 Object* ignoreCase = args[3]; 1864 Object* ignoreCase = args[3];
1865 if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value(); 1865 if (!ignoreCase->IsTrue()) ignoreCase = isolate->heap()->false_value();
1866 1866
1867 Object* multiline = args[4]; 1867 Object* multiline = args[4];
1868 if (!multiline->IsTrue()) multiline = isolate->heap()->false_value(); 1868 if (!multiline->IsTrue()) multiline = isolate->heap()->false_value();
1869 1869
1870 Map* map = regexp->map(); 1870 Map* map = regexp->map();
1871 Object* constructor = map->constructor(); 1871 Object* constructor = map->constructor();
1872 if (constructor->IsJSFunction() && 1872 if (constructor->IsJSFunction() &&
1873 JSFunction::cast(constructor)->initial_map() == map) { 1873 JSFunction::cast(constructor)->initial_map() == map) {
1874 // If we still have the original map, set in-object properties directly. 1874 // If we still have the original map, set in-object properties directly.
1875 regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source); 1875 regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1876 // Both true and false are immovable immortal objects so no need for write 1876 // Both true and false are immovable immortal objects so no need for write
1877 // barrier. 1877 // barrier.
1878 regexp->InObjectPropertyAtPut( 1878 regexp->InObjectPropertyAtPut(
1879 JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER); 1879 JSRegExp::kGlobalFieldIndex, global, SKIP_WRITE_BARRIER);
1880 regexp->InObjectPropertyAtPut( 1880 regexp->InObjectPropertyAtPut(
1881 JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER); 1881 JSRegExp::kIgnoreCaseFieldIndex, ignoreCase, SKIP_WRITE_BARRIER);
1882 regexp->InObjectPropertyAtPut( 1882 regexp->InObjectPropertyAtPut(
1883 JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER); 1883 JSRegExp::kMultilineFieldIndex, multiline, SKIP_WRITE_BARRIER);
1884 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, 1884 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1885 Smi::FromInt(0), 1885 Smi::FromInt(0),
1886 SKIP_WRITE_BARRIER); // It's a Smi. 1886 SKIP_WRITE_BARRIER); // It's a Smi.
1887 return regexp; 1887 return regexp;
1888 } 1888 }
1889 1889
1890 // Map has changed, so use generic, but slower, method. 1890 // Map has changed, so use generic, but slower, method.
1891 PropertyAttributes final = 1891 PropertyAttributes final =
1892 static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); 1892 static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
1893 PropertyAttributes writable = 1893 PropertyAttributes writable =
1894 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); 1894 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1895 Heap* heap = isolate->heap(); 1895 Heap* heap = isolate->heap();
1896 MaybeObject* result; 1896 MaybeObject* result;
1897 result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(), 1897 result = regexp->SetLocalPropertyIgnoreAttributes(heap->source_symbol(),
1898 source, 1898 source,
1899 final); 1899 final);
1900 ASSERT(!result->IsFailure()); 1900 ASSERT(!result->IsFailure());
1901 result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(), 1901 result = regexp->SetLocalPropertyIgnoreAttributes(heap->global_symbol(),
1902 global, 1902 global,
1903 final); 1903 final);
1904 ASSERT(!result->IsFailure()); 1904 ASSERT(!result->IsFailure());
1905 result = 1905 result =
1906 regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(), 1906 regexp->SetLocalPropertyIgnoreAttributes(heap->ignore_case_symbol(),
1907 ignoreCase, 1907 ignoreCase,
1908 final); 1908 final);
1909 ASSERT(!result->IsFailure()); 1909 ASSERT(!result->IsFailure());
1910 result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(), 1910 result = regexp->SetLocalPropertyIgnoreAttributes(heap->multiline_symbol(),
1911 multiline, 1911 multiline,
1912 final); 1912 final);
1913 ASSERT(!result->IsFailure()); 1913 ASSERT(!result->IsFailure());
1914 result = 1914 result =
1915 regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(), 1915 regexp->SetLocalPropertyIgnoreAttributes(heap->last_index_symbol(),
1916 Smi::FromInt(0), 1916 Smi::FromInt(0),
1917 writable); 1917 writable);
1918 ASSERT(!result->IsFailure()); 1918 ASSERT(!result->IsFailure());
1919 USE(result); 1919 USE(result);
1920 return regexp; 1920 return regexp;
1921 } 1921 }
1922 1922
1923 1923
1924 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) { 1924 RUNTIME_FUNCTION(MaybeObject*, Runtime_FinishArrayPrototypeSetup) {
1925 HandleScope scope(isolate); 1925 HandleScope scope(isolate);
1926 ASSERT(args.length() == 1); 1926 ASSERT(args.length() == 1);
1927 CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0); 1927 CONVERT_ARG_HANDLE_CHECKED(JSArray, prototype, 0);
1928 // This is necessary to enable fast checks for absence of elements 1928 // This is necessary to enable fast checks for absence of elements
1929 // on Array.prototype and below. 1929 // on Array.prototype and below.
1930 prototype->set_elements(isolate->heap()->empty_fixed_array()); 1930 prototype->set_elements(isolate->heap()->empty_fixed_array());
1931 return Smi::FromInt(0); 1931 return Smi::FromInt(0);
1932 } 1932 }
1933 1933
1934 1934
1935 static Handle<JSFunction> InstallBuiltin(Isolate* isolate, 1935 static Handle<JSFunction> InstallBuiltin(Isolate* isolate,
1936 Handle<JSObject> holder, 1936 Handle<JSObject> holder,
1937 const char* name, 1937 const char* name,
1938 Builtins::Name builtin_name) { 1938 Builtins::Name builtin_name) {
1939 Handle<String> key = isolate->factory()->LookupAsciiSymbol(name); 1939 Handle<String> key = isolate->factory()->LookupAsciiSymbol(name);
1940 Handle<Code> code(isolate->builtins()->builtin(builtin_name)); 1940 Handle<Code> code(isolate->builtins()->builtin(builtin_name));
1941 Handle<JSFunction> optimized = 1941 Handle<JSFunction> optimized =
1942 isolate->factory()->NewFunction(key, 1942 isolate->factory()->NewFunction(key,
1943 JS_OBJECT_TYPE, 1943 JS_OBJECT_TYPE,
1944 JSObject::kHeaderSize, 1944 JSObject::kHeaderSize,
1945 code, 1945 code,
1946 false); 1946 false);
1947 optimized->shared()->DontAdaptArguments(); 1947 optimized->shared()->DontAdaptArguments();
1948 JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode); 1948 JSReceiver::SetProperty(holder, key, optimized, NONE, kStrictMode);
1949 return optimized; 1949 return optimized;
1950 } 1950 }
1951 1951
1952 1952
1953 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) { 1953 RUNTIME_FUNCTION(MaybeObject*, Runtime_SpecialArrayFunctions) {
1954 HandleScope scope(isolate); 1954 HandleScope scope(isolate);
1955 ASSERT(args.length() == 1); 1955 ASSERT(args.length() == 1);
1956 CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0); 1956 CONVERT_ARG_HANDLE_CHECKED(JSObject, holder, 0);
1957 1957
1958 InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop); 1958 InstallBuiltin(isolate, holder, "pop", Builtins::kArrayPop);
1959 InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush); 1959 InstallBuiltin(isolate, holder, "push", Builtins::kArrayPush);
1960 InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift); 1960 InstallBuiltin(isolate, holder, "shift", Builtins::kArrayShift);
1961 InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift); 1961 InstallBuiltin(isolate, holder, "unshift", Builtins::kArrayUnshift);
1962 InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice); 1962 InstallBuiltin(isolate, holder, "slice", Builtins::kArraySlice);
1963 InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice); 1963 InstallBuiltin(isolate, holder, "splice", Builtins::kArraySplice);
1964 InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat); 1964 InstallBuiltin(isolate, holder, "concat", Builtins::kArrayConcat);
1965 1965
1966 return *holder; 1966 return *holder;
1967 } 1967 }
1968 1968
1969 1969
1970 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) { 1970 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetDefaultReceiver) {
1971 ASSERT(args.length() == 1); 1971 ASSERT(args.length() == 1);
1972 CONVERT_ARG_CHECKED(JSReceiver, callable, 0); 1972 CONVERT_ARG_CHECKED(JSReceiver, callable, 0);
1973 1973
1974 if (!callable->IsJSFunction()) { 1974 if (!callable->IsJSFunction()) {
1975 HandleScope scope(isolate); 1975 HandleScope scope(isolate);
1976 bool threw = false; 1976 bool threw = false;
1977 Handle<Object> delegate = 1977 Handle<Object> delegate =
1978 Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw); 1978 Execution::TryGetFunctionDelegate(Handle<JSReceiver>(callable), &threw);
1979 if (threw) return Failure::Exception(); 1979 if (threw) return Failure::Exception();
1980 callable = JSFunction::cast(*delegate); 1980 callable = JSFunction::cast(*delegate);
1981 } 1981 }
1982 JSFunction* function = JSFunction::cast(callable); 1982 JSFunction* function = JSFunction::cast(callable);
1983 1983
1984 SharedFunctionInfo* shared = function->shared(); 1984 SharedFunctionInfo* shared = function->shared();
1985 if (shared->native() || !shared->is_classic_mode()) { 1985 if (shared->native() || !shared->is_classic_mode()) {
1986 return isolate->heap()->undefined_value(); 1986 return isolate->heap()->undefined_value();
1987 } 1987 }
1988 // Returns undefined for strict or native functions, or 1988 // Returns undefined for strict or native functions, or
1989 // the associated global receiver for "normal" functions. 1989 // the associated global receiver for "normal" functions.
1990 1990
1991 Context* native_context = 1991 Context* native_context =
1992 function->context()->global_object()->native_context(); 1992 function->context()->global_object()->native_context();
1993 return native_context->global_object()->global_receiver(); 1993 return native_context->global_object()->global_receiver();
1994 } 1994 }
1995 1995
1996 1996
1997 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) { 1997 RUNTIME_FUNCTION(MaybeObject*, Runtime_MaterializeRegExpLiteral) {
1998 HandleScope scope(isolate); 1998 HandleScope scope(isolate);
1999 ASSERT(args.length() == 4); 1999 ASSERT(args.length() == 4);
2000 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0); 2000 CONVERT_ARG_HANDLE_CHECKED(FixedArray, literals, 0);
2001 int index = args.smi_at(1); 2001 int index = args.smi_at(1);
2002 Handle<String> pattern = args.at<String>(2); 2002 Handle<String> pattern = args.at<String>(2);
2003 Handle<String> flags = args.at<String>(3); 2003 Handle<String> flags = args.at<String>(3);
2004 2004
2005 // Get the RegExp function from the context in the literals array. 2005 // Get the RegExp function from the context in the literals array.
2006 // This is the RegExp function from the context in which the 2006 // This is the RegExp function from the context in which the
2007 // function was created. We do not use the RegExp function from the 2007 // function was created. We do not use the RegExp function from the
2008 // current native context because this might be the RegExp function 2008 // current native context because this might be the RegExp function
2009 // from another context which we should not have access to. 2009 // from another context which we should not have access to.
2010 Handle<JSFunction> constructor = 2010 Handle<JSFunction> constructor =
2011 Handle<JSFunction>( 2011 Handle<JSFunction>(
2012 JSFunction::NativeContextFromLiterals(*literals)->regexp_function()); 2012 JSFunction::NativeContextFromLiterals(*literals)->regexp_function());
2013 // Compute the regular expression literal. 2013 // Compute the regular expression literal.
2014 bool has_pending_exception; 2014 bool has_pending_exception;
2015 Handle<Object> regexp = 2015 Handle<Object> regexp =
2016 RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags, 2016 RegExpImpl::CreateRegExpLiteral(constructor, pattern, flags,
2017 &has_pending_exception); 2017 &has_pending_exception);
2018 if (has_pending_exception) { 2018 if (has_pending_exception) {
2019 ASSERT(isolate->has_pending_exception()); 2019 ASSERT(isolate->has_pending_exception());
2020 return Failure::Exception(); 2020 return Failure::Exception();
2021 } 2021 }
2022 literals->set(index, *regexp); 2022 literals->set(index, *regexp);
2023 return *regexp; 2023 return *regexp;
2024 } 2024 }
2025 2025
2026 2026
2027 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) { 2027 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetName) {
2028 NoHandleAllocation ha; 2028 NoHandleAllocation ha;
2029 ASSERT(args.length() == 1); 2029 ASSERT(args.length() == 1);
2030 2030
2031 CONVERT_ARG_CHECKED(JSFunction, f, 0); 2031 CONVERT_ARG_CHECKED(JSFunction, f, 0);
2032 return f->shared()->name(); 2032 return f->shared()->name();
2033 } 2033 }
2034 2034
2035 2035
2036 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) { 2036 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetName) {
2037 NoHandleAllocation ha; 2037 NoHandleAllocation ha;
2038 ASSERT(args.length() == 2); 2038 ASSERT(args.length() == 2);
2039 2039
2040 CONVERT_ARG_CHECKED(JSFunction, f, 0); 2040 CONVERT_ARG_CHECKED(JSFunction, f, 0);
2041 CONVERT_ARG_CHECKED(String, name, 1); 2041 CONVERT_ARG_CHECKED(String, name, 1);
2042 f->shared()->set_name(name); 2042 f->shared()->set_name(name);
2043 return isolate->heap()->undefined_value(); 2043 return isolate->heap()->undefined_value();
2044 } 2044 }
2045 2045
2046 2046
2047 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) { 2047 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionNameShouldPrintAsAnonymous) {
2048 NoHandleAllocation ha; 2048 NoHandleAllocation ha;
2049 ASSERT(args.length() == 1); 2049 ASSERT(args.length() == 1);
2050 CONVERT_ARG_CHECKED(JSFunction, f, 0); 2050 CONVERT_ARG_CHECKED(JSFunction, f, 0);
2051 return isolate->heap()->ToBoolean( 2051 return isolate->heap()->ToBoolean(
2052 f->shared()->name_should_print_as_anonymous()); 2052 f->shared()->name_should_print_as_anonymous());
2053 } 2053 }
2054 2054
2055 2055
2056 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) { 2056 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionMarkNameShouldPrintAsAnonymous) {
2057 NoHandleAllocation ha; 2057 NoHandleAllocation ha;
2058 ASSERT(args.length() == 1); 2058 ASSERT(args.length() == 1);
2059 CONVERT_ARG_CHECKED(JSFunction, f, 0); 2059 CONVERT_ARG_CHECKED(JSFunction, f, 0);
2060 f->shared()->set_name_should_print_as_anonymous(true); 2060 f->shared()->set_name_should_print_as_anonymous(true);
2061 return isolate->heap()->undefined_value(); 2061 return isolate->heap()->undefined_value();
2062 } 2062 }
2063 2063
2064 2064
2065 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) { 2065 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
2066 NoHandleAllocation ha; 2066 NoHandleAllocation ha;
2067 ASSERT(args.length() == 1); 2067 ASSERT(args.length() == 1);
2068 2068
2069 CONVERT_ARG_CHECKED(JSFunction, f, 0); 2069 CONVERT_ARG_CHECKED(JSFunction, f, 0);
2070 f->RemovePrototype(); 2070 f->RemovePrototype();
2071 2071
2072 return isolate->heap()->undefined_value(); 2072 return isolate->heap()->undefined_value();
2073 } 2073 }
2074 2074
2075 2075
2076 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) { 2076 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScript) {
2077 HandleScope scope(isolate); 2077 HandleScope scope(isolate);
2078 ASSERT(args.length() == 1); 2078 ASSERT(args.length() == 1);
2079 2079
2080 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 2080 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2081 Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate); 2081 Handle<Object> script = Handle<Object>(fun->shared()->script(), isolate);
2082 if (!script->IsScript()) return isolate->heap()->undefined_value(); 2082 if (!script->IsScript()) return isolate->heap()->undefined_value();
2083 2083
2084 return *GetScriptWrapper(Handle<Script>::cast(script)); 2084 return *GetScriptWrapper(Handle<Script>::cast(script));
2085 } 2085 }
2086 2086
2087 2087
2088 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) { 2088 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetSourceCode) {
2089 HandleScope scope(isolate); 2089 HandleScope scope(isolate);
2090 ASSERT(args.length() == 1); 2090 ASSERT(args.length() == 1);
2091 2091
2092 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0); 2092 CONVERT_ARG_HANDLE_CHECKED(JSFunction, f, 0);
2093 Handle<SharedFunctionInfo> shared(f->shared()); 2093 Handle<SharedFunctionInfo> shared(f->shared());
2094 return *shared->GetSourceCode(); 2094 return *shared->GetSourceCode();
2095 } 2095 }
2096 2096
2097 2097
2098 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) { 2098 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetScriptSourcePosition) {
2099 NoHandleAllocation ha; 2099 NoHandleAllocation ha;
2100 ASSERT(args.length() == 1); 2100 ASSERT(args.length() == 1);
2101 2101
2102 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 2102 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2103 int pos = fun->shared()->start_position(); 2103 int pos = fun->shared()->start_position();
2104 return Smi::FromInt(pos); 2104 return Smi::FromInt(pos);
2105 } 2105 }
2106 2106
2107 2107
2108 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) { 2108 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionGetPositionForOffset) {
2109 ASSERT(args.length() == 2); 2109 ASSERT(args.length() == 2);
2110 2110
2111 CONVERT_ARG_CHECKED(Code, code, 0); 2111 CONVERT_ARG_CHECKED(Code, code, 0);
2112 CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]); 2112 CONVERT_NUMBER_CHECKED(int, offset, Int32, args[1]);
2113 2113
2114 RUNTIME_ASSERT(0 <= offset && offset < code->Size()); 2114 RUNTIME_ASSERT(0 <= offset && offset < code->Size());
2115 2115
2116 Address pc = code->address() + offset; 2116 Address pc = code->address() + offset;
2117 return Smi::FromInt(code->SourcePosition(pc)); 2117 return Smi::FromInt(code->SourcePosition(pc));
2118 } 2118 }
2119 2119
2120 2120
2121 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) { 2121 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetInstanceClassName) {
2122 NoHandleAllocation ha; 2122 NoHandleAllocation ha;
2123 ASSERT(args.length() == 2); 2123 ASSERT(args.length() == 2);
2124 2124
2125 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 2125 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2126 CONVERT_ARG_CHECKED(String, name, 1); 2126 CONVERT_ARG_CHECKED(String, name, 1);
2127 fun->SetInstanceClassName(name); 2127 fun->SetInstanceClassName(name);
2128 return isolate->heap()->undefined_value(); 2128 return isolate->heap()->undefined_value();
2129 } 2129 }
2130 2130
2131 2131
2132 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) { 2132 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetLength) {
2133 NoHandleAllocation ha; 2133 NoHandleAllocation ha;
2134 ASSERT(args.length() == 2); 2134 ASSERT(args.length() == 2);
2135 2135
2136 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 2136 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2137 CONVERT_SMI_ARG_CHECKED(length, 1); 2137 CONVERT_SMI_ARG_CHECKED(length, 1);
2138 fun->shared()->set_length(length); 2138 fun->shared()->set_length(length);
2139 return isolate->heap()->undefined_value(); 2139 return isolate->heap()->undefined_value();
2140 } 2140 }
2141 2141
2142 2142
2143 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) { 2143 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetPrototype) {
2144 NoHandleAllocation ha; 2144 NoHandleAllocation ha;
2145 ASSERT(args.length() == 2); 2145 ASSERT(args.length() == 2);
2146 2146
2147 CONVERT_ARG_CHECKED(JSFunction, fun, 0); 2147 CONVERT_ARG_CHECKED(JSFunction, fun, 0);
2148 ASSERT(fun->should_have_prototype()); 2148 ASSERT(fun->should_have_prototype());
2149 Object* obj; 2149 Object* obj;
2150 { MaybeObject* maybe_obj = 2150 { MaybeObject* maybe_obj =
2151 Accessors::FunctionSetPrototype(fun, args[1], NULL); 2151 Accessors::FunctionSetPrototype(fun, args[1], NULL);
2152 if (!maybe_obj->ToObject(&obj)) return maybe_obj; 2152 if (!maybe_obj->ToObject(&obj)) return maybe_obj;
2153 } 2153 }
2154 return args[0]; // return TOS 2154 return args[0]; // return TOS
2155 } 2155 }
2156 2156
2157 2157
2158 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) { 2158 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionSetReadOnlyPrototype) {
2159 NoHandleAllocation ha; 2159 NoHandleAllocation ha;
2160 RUNTIME_ASSERT(args.length() == 1); 2160 RUNTIME_ASSERT(args.length() == 1);
2161 CONVERT_ARG_CHECKED(JSFunction, function, 0); 2161 CONVERT_ARG_CHECKED(JSFunction, function, 0);
2162 2162
2163 String* name = isolate->heap()->prototype_symbol(); 2163 String* name = isolate->heap()->prototype_symbol();
2164 2164
2165 if (function->HasFastProperties()) { 2165 if (function->HasFastProperties()) {
2166 // Construct a new field descriptor with updated attributes. 2166 // Construct a new field descriptor with updated attributes.
2167 DescriptorArray* instance_desc = function->map()->instance_descriptors(); 2167 DescriptorArray* instance_desc = function->map()->instance_descriptors();
2168 2168
2169 int index = instance_desc->SearchWithCache(name, function->map()); 2169 int index = instance_desc->SearchWithCache(name);
2170 ASSERT(index != DescriptorArray::kNotFound); 2170 ASSERT(index != DescriptorArray::kNotFound);
2171 PropertyDetails details = instance_desc->GetDetails(index); 2171 PropertyDetails details = instance_desc->GetDetails(index);
2172 2172
2173 CallbacksDescriptor new_desc(name, 2173 CallbacksDescriptor new_desc(name,
2174 instance_desc->GetValue(index), 2174 instance_desc->GetValue(index),
2175 static_cast<PropertyAttributes>(details.attributes() | READ_ONLY), 2175 static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2176 details.descriptor_index()); 2176 details.descriptor_index());
2177 2177
2178 // Create a new map featuring the new field descriptors array. 2178 // Create a new map featuring the new field descriptors array.
2179 Map* new_map; 2179 Map* new_map;
2180 MaybeObject* maybe_map = 2180 MaybeObject* maybe_map =
2181 function->map()->CopyReplaceDescriptor( 2181 function->map()->CopyReplaceDescriptor(
2182 &new_desc, index, OMIT_TRANSITION); 2182 &new_desc, index, OMIT_TRANSITION);
2183 if (!maybe_map->To(&new_map)) return maybe_map; 2183 if (!maybe_map->To(&new_map)) return maybe_map;
2184 2184
2185 function->set_map(new_map); 2185 function->set_map(new_map);
2186 } else { // Dictionary properties. 2186 } else { // Dictionary properties.
2187 // Directly manipulate the property details. 2187 // Directly manipulate the property details.
2188 int entry = function->property_dictionary()->FindEntry(name); 2188 int entry = function->property_dictionary()->FindEntry(name);
2189 ASSERT(entry != StringDictionary::kNotFound); 2189 ASSERT(entry != StringDictionary::kNotFound);
2190 PropertyDetails details = function->property_dictionary()->DetailsAt(entry); 2190 PropertyDetails details = function->property_dictionary()->DetailsAt(entry);
2191 PropertyDetails new_details( 2191 PropertyDetails new_details(
2192 static_cast<PropertyAttributes>(details.attributes() | READ_ONLY), 2192 static_cast<PropertyAttributes>(details.attributes() | READ_ONLY),
2193 details.type(), 2193 details.type(),
2194 details.dictionary_index()); 2194 details.dictionary_index());
2195 function->property_dictionary()->DetailsAtPut(entry, new_details); 2195 function->property_dictionary()->DetailsAtPut(entry, new_details);
2196 } 2196 }
2197 return function; 2197 return function;
2198 } 2198 }
2199 2199
2200 2200
2201 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) { 2201 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsAPIFunction) {
2202 NoHandleAllocation ha; 2202 NoHandleAllocation ha;
2203 ASSERT(args.length() == 1); 2203 ASSERT(args.length() == 1);
2204 2204
2205 CONVERT_ARG_CHECKED(JSFunction, f, 0); 2205 CONVERT_ARG_CHECKED(JSFunction, f, 0);
2206 return isolate->heap()->ToBoolean(f->shared()->IsApiFunction()); 2206 return isolate->heap()->ToBoolean(f->shared()->IsApiFunction());
2207 } 2207 }
2208 2208
2209 2209
2210 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) { 2210 RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionIsBuiltin) {
2211 NoHandleAllocation ha; 2211 NoHandleAllocation ha;
2212 ASSERT(args.length() == 1); 2212 ASSERT(args.length() == 1);
2213 2213
2214 CONVERT_ARG_CHECKED(JSFunction, f, 0); 2214 CONVERT_ARG_CHECKED(JSFunction, f, 0);
2215 return isolate->heap()->ToBoolean(f->IsBuiltin()); 2215 return isolate->heap()->ToBoolean(f->IsBuiltin());
2216 } 2216 }
2217 2217
2218 2218
2219 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) { 2219 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
2220 HandleScope scope(isolate); 2220 HandleScope scope(isolate);
2221 ASSERT(args.length() == 2); 2221 ASSERT(args.length() == 2);
2222 2222
2223 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0); 2223 CONVERT_ARG_HANDLE_CHECKED(JSFunction, target, 0);
2224 Handle<Object> code = args.at<Object>(1); 2224 Handle<Object> code = args.at<Object>(1);
2225 2225
2226 if (code->IsNull()) return *target; 2226 if (code->IsNull()) return *target;
2227 RUNTIME_ASSERT(code->IsJSFunction()); 2227 RUNTIME_ASSERT(code->IsJSFunction());
2228 Handle<JSFunction> source = Handle<JSFunction>::cast(code); 2228 Handle<JSFunction> source = Handle<JSFunction>::cast(code);
2229 Handle<SharedFunctionInfo> target_shared(target->shared()); 2229 Handle<SharedFunctionInfo> target_shared(target->shared());
2230 Handle<SharedFunctionInfo> source_shared(source->shared()); 2230 Handle<SharedFunctionInfo> source_shared(source->shared());
2231 2231
2232 if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) { 2232 if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
2233 return Failure::Exception(); 2233 return Failure::Exception();
2234 } 2234 }
2235 2235
2236 // Set the code, scope info, formal parameter count, and the length 2236 // Set the code, scope info, formal parameter count, and the length
2237 // of the target shared function info. Set the source code of the 2237 // of the target shared function info. Set the source code of the
2238 // target function to undefined. SetCode is only used for built-in 2238 // target function to undefined. SetCode is only used for built-in
2239 // constructors like String, Array, and Object, and some web code 2239 // constructors like String, Array, and Object, and some web code
2240 // doesn't like seeing source code for constructors. 2240 // doesn't like seeing source code for constructors.
2241 target_shared->set_code(source_shared->code()); 2241 target_shared->set_code(source_shared->code());
2242 target_shared->set_scope_info(source_shared->scope_info()); 2242 target_shared->set_scope_info(source_shared->scope_info());
2243 target_shared->set_length(source_shared->length()); 2243 target_shared->set_length(source_shared->length());
2244 target_shared->set_formal_parameter_count( 2244 target_shared->set_formal_parameter_count(
2245 source_shared->formal_parameter_count()); 2245 source_shared->formal_parameter_count());
2246 target_shared->set_script(isolate->heap()->undefined_value()); 2246 target_shared->set_script(isolate->heap()->undefined_value());
2247 2247
2248 // Since we don't store the source we should never optimize this. 2248 // Since we don't store the source we should never optimize this.
2249 target_shared->code()->set_optimizable(false); 2249 target_shared->code()->set_optimizable(false);
2250 2250
2251 // Clear the optimization hints related to the compiled code as these 2251 // Clear the optimization hints related to the compiled code as these
2252 // are no longer valid when the code is overwritten. 2252 // are no longer valid when the code is overwritten.
2253 target_shared->ClearThisPropertyAssignmentsInfo(); 2253 target_shared->ClearThisPropertyAssignmentsInfo();
2254 2254
2255 // Set the code of the target function. 2255 // Set the code of the target function.
2256 target->ReplaceCode(source_shared->code()); 2256 target->ReplaceCode(source_shared->code());
2257 2257
2258 // Make sure we get a fresh copy of the literal vector to avoid cross 2258 // Make sure we get a fresh copy of the literal vector to avoid cross
2259 // context contamination. 2259 // context contamination.
2260 Handle<Context> context(source->context()); 2260 Handle<Context> context(source->context());
2261 int number_of_literals = source->NumberOfLiterals(); 2261 int number_of_literals = source->NumberOfLiterals();
2262 Handle<FixedArray> literals = 2262 Handle<FixedArray> literals =
2263 isolate->factory()->NewFixedArray(number_of_literals, TENURED); 2263 isolate->factory()->NewFixedArray(number_of_literals, TENURED);
2264 if (number_of_literals > 0) { 2264 if (number_of_literals > 0) {
2265 literals->set(JSFunction::kLiteralNativeContextIndex, 2265 literals->set(JSFunction::kLiteralNativeContextIndex,
2266 context->native_context()); 2266 context->native_context());
2267 } 2267 }
2268 target->set_context(*context); 2268 target->set_context(*context);
2269 target->set_literals(*literals); 2269 target->set_literals(*literals);
2270 target->set_next_function_link(isolate->heap()->undefined_value()); 2270 target->set_next_function_link(isolate->heap()->undefined_value());
2271 2271
2272 if (isolate->logger()->is_logging_code_events() || 2272 if (isolate->logger()->is_logging_code_events() ||
2273 CpuProfiler::is_profiling(isolate)) { 2273 CpuProfiler::is_profiling(isolate)) {
2274 isolate->logger()->LogExistingFunction( 2274 isolate->logger()->LogExistingFunction(
2275 source_shared, Handle<Code>(source_shared->code())); 2275 source_shared, Handle<Code>(source_shared->code()));
2276 } 2276 }
2277 2277
2278 return *target; 2278 return *target;
2279 } 2279 }
2280 2280
2281 2281
2282 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) { 2282 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetExpectedNumberOfProperties) {
2283 HandleScope scope(isolate); 2283 HandleScope scope(isolate);
2284 ASSERT(args.length() == 2); 2284 ASSERT(args.length() == 2);
2285 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0); 2285 CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
2286 CONVERT_SMI_ARG_CHECKED(num, 1); 2286 CONVERT_SMI_ARG_CHECKED(num, 1);
2287 RUNTIME_ASSERT(num >= 0); 2287 RUNTIME_ASSERT(num >= 0);
2288 SetExpectedNofProperties(function, num); 2288 SetExpectedNofProperties(function, num);
2289 return isolate->heap()->undefined_value(); 2289 return isolate->heap()->undefined_value();
2290 } 2290 }
2291 2291
2292 2292
2293 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate, 2293 MUST_USE_RESULT static MaybeObject* CharFromCode(Isolate* isolate,
2294 Object* char_code) { 2294 Object* char_code) {
2295 uint32_t code; 2295 uint32_t code;
2296 if (char_code->ToArrayIndex(&code)) { 2296 if (char_code->ToArrayIndex(&code)) {
2297 if (code <= 0xffff) { 2297 if (code <= 0xffff) {
2298 return isolate->heap()->LookupSingleCharacterStringFromCode(code); 2298 return isolate->heap()->LookupSingleCharacterStringFromCode(code);
2299 } 2299 }
2300 } 2300 }
2301 return isolate->heap()->empty_string(); 2301 return isolate->heap()->empty_string();
2302 } 2302 }
2303 2303
2304 2304
2305 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) { 2305 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
2306 NoHandleAllocation ha; 2306 NoHandleAllocation ha;
2307 ASSERT(args.length() == 2); 2307 ASSERT(args.length() == 2);
2308 2308
2309 CONVERT_ARG_CHECKED(String, subject, 0); 2309 CONVERT_ARG_CHECKED(String, subject, 0);
2310 CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]); 2310 CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
2311 2311
2312 // Flatten the string. If someone wants to get a char at an index 2312 // Flatten the string. If someone wants to get a char at an index
2313 // in a cons string, it is likely that more indices will be 2313 // in a cons string, it is likely that more indices will be
2314 // accessed. 2314 // accessed.
2315 Object* flat; 2315 Object* flat;
2316 { MaybeObject* maybe_flat = subject->TryFlatten(); 2316 { MaybeObject* maybe_flat = subject->TryFlatten();
2317 if (!maybe_flat->ToObject(&flat)) return maybe_flat; 2317 if (!maybe_flat->ToObject(&flat)) return maybe_flat;
2318 } 2318 }
2319 subject = String::cast(flat); 2319 subject = String::cast(flat);
2320 2320
2321 if (i >= static_cast<uint32_t>(subject->length())) { 2321 if (i >= static_cast<uint32_t>(subject->length())) {
2322 return isolate->heap()->nan_value(); 2322 return isolate->heap()->nan_value();
2323 } 2323 }
2324 2324
2325 return Smi::FromInt(subject->Get(i)); 2325 return Smi::FromInt(subject->Get(i));
2326 } 2326 }
2327 2327
2328 2328
2329 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) { 2329 RUNTIME_FUNCTION(MaybeObject*, Runtime_CharFromCode) {
2330 NoHandleAllocation ha; 2330 NoHandleAllocation ha;
2331 ASSERT(args.length() == 1); 2331 ASSERT(args.length() == 1);
2332 return CharFromCode(isolate, args[0]); 2332 return CharFromCode(isolate, args[0]);
2333 } 2333 }
2334 2334
2335 2335
2336 class FixedArrayBuilder { 2336 class FixedArrayBuilder {
2337 public: 2337 public:
2338 explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity) 2338 explicit FixedArrayBuilder(Isolate* isolate, int initial_capacity)
2339 : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)), 2339 : array_(isolate->factory()->NewFixedArrayWithHoles(initial_capacity)),
2340 length_(0), 2340 length_(0),
2341 has_non_smi_elements_(false) { 2341 has_non_smi_elements_(false) {
2342 // Require a non-zero initial size. Ensures that doubling the size to 2342 // Require a non-zero initial size. Ensures that doubling the size to
2343 // extend the array will work. 2343 // extend the array will work.
2344 ASSERT(initial_capacity > 0); 2344 ASSERT(initial_capacity > 0);
2345 } 2345 }
2346 2346
2347 explicit FixedArrayBuilder(Handle<FixedArray> backing_store) 2347 explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
2348 : array_(backing_store), 2348 : array_(backing_store),
2349 length_(0), 2349 length_(0),
2350 has_non_smi_elements_(false) { 2350 has_non_smi_elements_(false) {
2351 // Require a non-zero initial size. Ensures that doubling the size to 2351 // Require a non-zero initial size. Ensures that doubling the size to
2352 // extend the array will work. 2352 // extend the array will work.
2353 ASSERT(backing_store->length() > 0); 2353 ASSERT(backing_store->length() > 0);
2354 } 2354 }
2355 2355
2356 bool HasCapacity(int elements) { 2356 bool HasCapacity(int elements) {
2357 int length = array_->length(); 2357 int length = array_->length();
2358 int required_length = length_ + elements; 2358 int required_length = length_ + elements;
2359 return (length >= required_length); 2359 return (length >= required_length);
2360 } 2360 }
2361 2361
2362 void EnsureCapacity(int elements) { 2362 void EnsureCapacity(int elements) {
2363 int length = array_->length(); 2363 int length = array_->length();
2364 int required_length = length_ + elements; 2364 int required_length = length_ + elements;
2365 if (length < required_length) { 2365 if (length < required_length) {
2366 int new_length = length; 2366 int new_length = length;
2367 do { 2367 do {
2368 new_length *= 2; 2368 new_length *= 2;
2369 } while (new_length < required_length); 2369 } while (new_length < required_length);
2370 Handle<FixedArray> extended_array = 2370 Handle<FixedArray> extended_array =
2371 array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length); 2371 array_->GetIsolate()->factory()->NewFixedArrayWithHoles(new_length);
2372 array_->CopyTo(0, *extended_array, 0, length_); 2372 array_->CopyTo(0, *extended_array, 0, length_);
2373 array_ = extended_array; 2373 array_ = extended_array;
2374 } 2374 }
2375 } 2375 }
2376 2376
2377 void Add(Object* value) { 2377 void Add(Object* value) {
2378 ASSERT(!value->IsSmi()); 2378 ASSERT(!value->IsSmi());
2379 ASSERT(length_ < capacity()); 2379 ASSERT(length_ < capacity());
2380 array_->set(length_, value); 2380 array_->set(length_, value);
2381 length_++; 2381 length_++;
2382 has_non_smi_elements_ = true; 2382 has_non_smi_elements_ = true;
2383 } 2383 }
2384 2384
2385 void Add(Smi* value) { 2385 void Add(Smi* value) {
2386 ASSERT(value->IsSmi()); 2386 ASSERT(value->IsSmi());
2387 ASSERT(length_ < capacity()); 2387 ASSERT(length_ < capacity());
2388 array_->set(length_, value); 2388 array_->set(length_, value);
2389 length_++; 2389 length_++;
2390 } 2390 }
2391 2391
2392 Handle<FixedArray> array() { 2392 Handle<FixedArray> array() {
2393 return array_; 2393 return array_;
2394 } 2394 }
2395 2395
2396 int length() { 2396 int length() {
2397 return length_; 2397 return length_;
2398 } 2398 }
2399 2399
2400 int capacity() { 2400 int capacity() {
2401 return array_->length(); 2401 return array_->length();
2402 } 2402 }
2403 2403
2404 Handle<JSArray> ToJSArray(Handle<JSArray> target_array) { 2404 Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
2405 FACTORY->SetContent(target_array, array_); 2405 FACTORY->SetContent(target_array, array_);
2406 target_array->set_length(Smi::FromInt(length_)); 2406 target_array->set_length(Smi::FromInt(length_));
2407 return target_array; 2407 return target_array;
2408 } 2408 }
2409 2409
2410 2410
2411 private: 2411 private:
2412 Handle<FixedArray> array_; 2412 Handle<FixedArray> array_;
2413 int length_; 2413 int length_;
2414 bool has_non_smi_elements_; 2414 bool has_non_smi_elements_;
2415 }; 2415 };
2416 2416
2417 2417
2418 // Forward declarations. 2418 // Forward declarations.
2419 const int kStringBuilderConcatHelperLengthBits = 11; 2419 const int kStringBuilderConcatHelperLengthBits = 11;
2420 const int kStringBuilderConcatHelperPositionBits = 19; 2420 const int kStringBuilderConcatHelperPositionBits = 19;
2421 2421
2422 template <typename schar> 2422 template <typename schar>
2423 static inline void StringBuilderConcatHelper(String*, 2423 static inline void StringBuilderConcatHelper(String*,
2424 schar*, 2424 schar*,
2425 FixedArray*, 2425 FixedArray*,
2426 int); 2426 int);
2427 2427
2428 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits> 2428 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
2429 StringBuilderSubstringLength; 2429 StringBuilderSubstringLength;
2430 typedef BitField<int, 2430 typedef BitField<int,
2431 kStringBuilderConcatHelperLengthBits, 2431 kStringBuilderConcatHelperLengthBits,
2432 kStringBuilderConcatHelperPositionBits> 2432 kStringBuilderConcatHelperPositionBits>
2433 StringBuilderSubstringPosition; 2433 StringBuilderSubstringPosition;
2434 2434
2435 2435
2436 class ReplacementStringBuilder { 2436 class ReplacementStringBuilder {
2437 public: 2437 public:
2438 ReplacementStringBuilder(Heap* heap, 2438 ReplacementStringBuilder(Heap* heap,
2439 Handle<String> subject, 2439 Handle<String> subject,
2440 int estimated_part_count) 2440 int estimated_part_count)
2441 : heap_(heap), 2441 : heap_(heap),
2442 array_builder_(heap->isolate(), estimated_part_count), 2442 array_builder_(heap->isolate(), estimated_part_count),
2443 subject_(subject), 2443 subject_(subject),
2444 character_count_(0), 2444 character_count_(0),
2445 is_ascii_(subject->IsAsciiRepresentation()) { 2445 is_ascii_(subject->IsAsciiRepresentation()) {
2446 // Require a non-zero initial size. Ensures that doubling the size to 2446 // Require a non-zero initial size. Ensures that doubling the size to
2447 // extend the array will work. 2447 // extend the array will work.
2448 ASSERT(estimated_part_count > 0); 2448 ASSERT(estimated_part_count > 0);
2449 } 2449 }
2450 2450
2451 static inline void AddSubjectSlice(FixedArrayBuilder* builder, 2451 static inline void AddSubjectSlice(FixedArrayBuilder* builder,
2452 int from, 2452 int from,
2453 int to) { 2453 int to) {
2454 ASSERT(from >= 0); 2454 ASSERT(from >= 0);
2455 int length = to - from; 2455 int length = to - from;
2456 ASSERT(length > 0); 2456 ASSERT(length > 0);
2457 if (StringBuilderSubstringLength::is_valid(length) && 2457 if (StringBuilderSubstringLength::is_valid(length) &&
2458 StringBuilderSubstringPosition::is_valid(from)) { 2458 StringBuilderSubstringPosition::is_valid(from)) {
2459 int encoded_slice = StringBuilderSubstringLength::encode(length) | 2459 int encoded_slice = StringBuilderSubstringLength::encode(length) |
2460 StringBuilderSubstringPosition::encode(from); 2460 StringBuilderSubstringPosition::encode(from);
2461 builder->Add(Smi::FromInt(encoded_slice)); 2461 builder->Add(Smi::FromInt(encoded_slice));
2462 } else { 2462 } else {
2463 // Otherwise encode as two smis. 2463 // Otherwise encode as two smis.
2464 builder->Add(Smi::FromInt(-length)); 2464 builder->Add(Smi::FromInt(-length));
2465 builder->Add(Smi::FromInt(from)); 2465 builder->Add(Smi::FromInt(from));
2466 } 2466 }
2467 } 2467 }
2468 2468
2469 2469
2470 void EnsureCapacity(int elements) { 2470 void EnsureCapacity(int elements) {
2471 array_builder_.EnsureCapacity(elements); 2471 array_builder_.EnsureCapacity(elements);
2472 } 2472 }
2473 2473
2474 2474
2475 void AddSubjectSlice(int from, int to) { 2475 void AddSubjectSlice(int from, int to) {
2476 AddSubjectSlice(&array_builder_, from, to); 2476 AddSubjectSlice(&array_builder_, from, to);
2477 IncrementCharacterCount(to - from); 2477 IncrementCharacterCount(to - from);
2478 } 2478 }
2479 2479
2480 2480
2481 void AddString(Handle<String> string) { 2481 void AddString(Handle<String> string) {
2482 int length = string->length(); 2482 int length = string->length();
2483 ASSERT(length > 0); 2483 ASSERT(length > 0);
2484 AddElement(*string); 2484 AddElement(*string);
2485 if (!string->IsAsciiRepresentation()) { 2485 if (!string->IsAsciiRepresentation()) {
2486 is_ascii_ = false; 2486 is_ascii_ = false;
2487 } 2487 }
2488 IncrementCharacterCount(length); 2488 IncrementCharacterCount(length);
2489 } 2489 }
2490 2490
2491 2491
2492 Handle<String> ToString() { 2492 Handle<String> ToString() {
2493 if (array_builder_.length() == 0) { 2493 if (array_builder_.length() == 0) {
2494 return heap_->isolate()->factory()->empty_string(); 2494 return heap_->isolate()->factory()->empty_string();
2495 } 2495 }
2496 2496
2497 Handle<String> joined_string; 2497 Handle<String> joined_string;
2498 if (is_ascii_) { 2498 if (is_ascii_) {
2499 Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_); 2499 Handle<SeqAsciiString> seq = NewRawAsciiString(character_count_);
2500 AssertNoAllocation no_alloc; 2500 AssertNoAllocation no_alloc;
2501 char* char_buffer = seq->GetChars(); 2501 char* char_buffer = seq->GetChars();
2502 StringBuilderConcatHelper(*subject_, 2502 StringBuilderConcatHelper(*subject_,
2503 char_buffer, 2503 char_buffer,
2504 *array_builder_.array(), 2504 *array_builder_.array(),
2505 array_builder_.length()); 2505 array_builder_.length());
2506 joined_string = Handle<String>::cast(seq); 2506 joined_string = Handle<String>::cast(seq);
2507 } else { 2507 } else {
2508 // Non-ASCII. 2508 // Non-ASCII.
2509 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_); 2509 Handle<SeqTwoByteString> seq = NewRawTwoByteString(character_count_);
2510 AssertNoAllocation no_alloc; 2510 AssertNoAllocation no_alloc;
2511 uc16* char_buffer = seq->GetChars(); 2511 uc16* char_buffer = seq->GetChars();
2512 StringBuilderConcatHelper(*subject_, 2512 StringBuilderConcatHelper(*subject_,
2513 char_buffer, 2513 char_buffer,
2514 *array_builder_.array(), 2514 *array_builder_.array(),
2515 array_builder_.length()); 2515 array_builder_.length());
2516 joined_string = Handle<String>::cast(seq); 2516 joined_string = Handle<String>::cast(seq);
2517 } 2517 }
2518 return joined_string; 2518 return joined_string;
2519 } 2519 }
2520 2520
2521 2521
2522 void IncrementCharacterCount(int by) { 2522 void IncrementCharacterCount(int by) {
2523 if (character_count_ > String::kMaxLength - by) { 2523 if (character_count_ > String::kMaxLength - by) {
2524 V8::FatalProcessOutOfMemory("String.replace result too large."); 2524 V8::FatalProcessOutOfMemory("String.replace result too large.");
2525 } 2525 }
2526 character_count_ += by; 2526 character_count_ += by;
2527 } 2527 }
2528 2528
2529 private: 2529 private:
2530 Handle<SeqAsciiString> NewRawAsciiString(int length) { 2530 Handle<SeqAsciiString> NewRawAsciiString(int length) {
2531 return heap_->isolate()->factory()->NewRawAsciiString(length); 2531 return heap_->isolate()->factory()->NewRawAsciiString(length);
2532 } 2532 }
2533 2533
2534 2534
2535 Handle<SeqTwoByteString> NewRawTwoByteString(int length) { 2535 Handle<SeqTwoByteString> NewRawTwoByteString(int length) {
2536 return heap_->isolate()->factory()->NewRawTwoByteString(length); 2536 return heap_->isolate()->factory()->NewRawTwoByteString(length);
2537 } 2537 }
2538 2538
2539 2539
2540 void AddElement(Object* element) { 2540 void AddElement(Object* element) {
2541 ASSERT(element->IsSmi() || element->IsString()); 2541 ASSERT(element->IsSmi() || element->IsString());
2542 ASSERT(array_builder_.capacity() > array_builder_.length()); 2542 ASSERT(array_builder_.capacity() > array_builder_.length());
2543 array_builder_.Add(element); 2543 array_builder_.Add(element);
2544 } 2544 }
2545 2545
2546 Heap* heap_; 2546 Heap* heap_;
2547 FixedArrayBuilder array_builder_; 2547 FixedArrayBuilder array_builder_;
2548 Handle<String> subject_; 2548 Handle<String> subject_;
2549 int character_count_; 2549 int character_count_;
2550 bool is_ascii_; 2550 bool is_ascii_;
2551 }; 2551 };
2552 2552
2553 2553
2554 class CompiledReplacement { 2554 class CompiledReplacement {
2555 public: 2555 public:
2556 explicit CompiledReplacement(Zone* zone) 2556 explicit CompiledReplacement(Zone* zone)
2557 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {} 2557 : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
2558 2558
2559 // Return whether the replacement is simple. 2559 // Return whether the replacement is simple.
2560 bool Compile(Handle<String> replacement, 2560 bool Compile(Handle<String> replacement,
2561 int capture_count, 2561 int capture_count,
2562 int subject_length); 2562 int subject_length);
2563 2563
2564 // Use Apply only if Compile returned false. 2564 // Use Apply only if Compile returned false.
2565 void Apply(ReplacementStringBuilder* builder, 2565 void Apply(ReplacementStringBuilder* builder,
2566 int match_from, 2566 int match_from,
2567 int match_to, 2567 int match_to,
2568 int32_t* match); 2568 int32_t* match);
2569 2569
2570 // Number of distinct parts of the replacement pattern. 2570 // Number of distinct parts of the replacement pattern.
2571 int parts() { 2571 int parts() {
2572 return parts_.length(); 2572 return parts_.length();
2573 } 2573 }
2574 2574
2575 Zone* zone() const { return zone_; } 2575 Zone* zone() const { return zone_; }
2576 2576
2577 private: 2577 private:
2578 enum PartType { 2578 enum PartType {
2579 SUBJECT_PREFIX = 1, 2579 SUBJECT_PREFIX = 1,
2580 SUBJECT_SUFFIX, 2580 SUBJECT_SUFFIX,
2581 SUBJECT_CAPTURE, 2581 SUBJECT_CAPTURE,
2582 REPLACEMENT_SUBSTRING, 2582 REPLACEMENT_SUBSTRING,
2583 REPLACEMENT_STRING, 2583 REPLACEMENT_STRING,
2584 2584
2585 NUMBER_OF_PART_TYPES 2585 NUMBER_OF_PART_TYPES
2586 }; 2586 };
2587 2587
2588 struct ReplacementPart { 2588 struct ReplacementPart {
2589 static inline ReplacementPart SubjectMatch() { 2589 static inline ReplacementPart SubjectMatch() {
2590 return ReplacementPart(SUBJECT_CAPTURE, 0); 2590 return ReplacementPart(SUBJECT_CAPTURE, 0);
2591 } 2591 }
2592 static inline ReplacementPart SubjectCapture(int capture_index) { 2592 static inline ReplacementPart SubjectCapture(int capture_index) {
2593 return ReplacementPart(SUBJECT_CAPTURE, capture_index); 2593 return ReplacementPart(SUBJECT_CAPTURE, capture_index);
2594 } 2594 }
2595 static inline ReplacementPart SubjectPrefix() { 2595 static inline ReplacementPart SubjectPrefix() {
2596 return ReplacementPart(SUBJECT_PREFIX, 0); 2596 return ReplacementPart(SUBJECT_PREFIX, 0);
2597 } 2597 }
2598 static inline ReplacementPart SubjectSuffix(int subject_length) { 2598 static inline ReplacementPart SubjectSuffix(int subject_length) {
2599 return ReplacementPart(SUBJECT_SUFFIX, subject_length); 2599 return ReplacementPart(SUBJECT_SUFFIX, subject_length);
2600 } 2600 }
2601 static inline ReplacementPart ReplacementString() { 2601 static inline ReplacementPart ReplacementString() {
2602 return ReplacementPart(REPLACEMENT_STRING, 0); 2602 return ReplacementPart(REPLACEMENT_STRING, 0);
2603 } 2603 }
2604 static inline ReplacementPart ReplacementSubString(int from, int to) { 2604 static inline ReplacementPart ReplacementSubString(int from, int to) {
2605 ASSERT(from >= 0); 2605 ASSERT(from >= 0);
2606 ASSERT(to > from); 2606 ASSERT(to > from);
2607 return ReplacementPart(-from, to); 2607 return ReplacementPart(-from, to);
2608 } 2608 }
2609 2609
2610 // If tag <= 0 then it is the negation of a start index of a substring of 2610 // If tag <= 0 then it is the negation of a start index of a substring of
2611 // the replacement pattern, otherwise it's a value from PartType. 2611 // the replacement pattern, otherwise it's a value from PartType.
2612 ReplacementPart(int tag, int data) 2612 ReplacementPart(int tag, int data)
2613 : tag(tag), data(data) { 2613 : tag(tag), data(data) {
2614 // Must be non-positive or a PartType value. 2614 // Must be non-positive or a PartType value.
2615 ASSERT(tag < NUMBER_OF_PART_TYPES); 2615 ASSERT(tag < NUMBER_OF_PART_TYPES);
2616 } 2616 }
2617 // Either a value of PartType or a non-positive number that is 2617 // Either a value of PartType or a non-positive number that is
2618 // the negation of an index into the replacement string. 2618 // the negation of an index into the replacement string.
2619 int tag; 2619 int tag;
2620 // The data value's interpretation depends on the value of tag: 2620 // The data value's interpretation depends on the value of tag:
2621 // tag == SUBJECT_PREFIX || 2621 // tag == SUBJECT_PREFIX ||
2622 // tag == SUBJECT_SUFFIX: data is unused. 2622 // tag == SUBJECT_SUFFIX: data is unused.
2623 // tag == SUBJECT_CAPTURE: data is the number of the capture. 2623 // tag == SUBJECT_CAPTURE: data is the number of the capture.
2624 // tag == REPLACEMENT_SUBSTRING || 2624 // tag == REPLACEMENT_SUBSTRING ||
2625 // tag == REPLACEMENT_STRING: data is index into array of substrings 2625 // tag == REPLACEMENT_STRING: data is index into array of substrings
2626 // of the replacement string. 2626 // of the replacement string.
2627 // tag <= 0: Temporary representation of the substring of the replacement 2627 // tag <= 0: Temporary representation of the substring of the replacement
2628 // string ranging over -tag .. data. 2628 // string ranging over -tag .. data.
2629 // Is replaced by REPLACEMENT_{SUB,}STRING when we create the 2629 // Is replaced by REPLACEMENT_{SUB,}STRING when we create the
2630 // substring objects. 2630 // substring objects.
2631 int data; 2631 int data;
2632 }; 2632 };
2633 2633
2634 template<typename Char> 2634 template<typename Char>
2635 bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts, 2635 bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
2636 Vector<Char> characters, 2636 Vector<Char> characters,
2637 int capture_count, 2637 int capture_count,
2638 int subject_length, 2638 int subject_length,
2639 Zone* zone) { 2639 Zone* zone) {
2640 int length = characters.length(); 2640 int length = characters.length();
2641 int last = 0; 2641 int last = 0;
2642 for (int i = 0; i < length; i++) { 2642 for (int i = 0; i < length; i++) {
2643 Char c = characters[i]; 2643 Char c = characters[i];
2644 if (c == '$') { 2644 if (c == '$') {
2645 int next_index = i + 1; 2645 int next_index = i + 1;
2646 if (next_index == length) { // No next character! 2646 if (next_index == length) { // No next character!
2647 break; 2647 break;
2648 } 2648 }
2649 Char c2 = characters[next_index]; 2649 Char c2 = characters[next_index];
2650 switch (c2) { 2650 switch (c2) {
2651 case '$': 2651 case '$':
2652 if (i > last) { 2652 if (i > last) {
2653 // There is a substring before. Include the first "$". 2653 // There is a substring before. Include the first "$".
2654 parts->Add(ReplacementPart::ReplacementSubString(last, next_index), 2654 parts->Add(ReplacementPart::ReplacementSubString(last, next_index),
2655 zone); 2655 zone);
2656 last = next_index + 1; // Continue after the second "$". 2656 last = next_index + 1; // Continue after the second "$".
2657 } else { 2657 } else {
2658 // Let the next substring start with the second "$". 2658 // Let the next substring start with the second "$".
2659 last = next_index; 2659 last = next_index;
2660 } 2660 }
2661 i = next_index; 2661 i = next_index;
2662 break; 2662 break;
2663 case '`': 2663 case '`':
2664 if (i > last) { 2664 if (i > last) {
2665 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone); 2665 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2666 } 2666 }
2667 parts->Add(ReplacementPart::SubjectPrefix(), zone); 2667 parts->Add(ReplacementPart::SubjectPrefix(), zone);
2668 i = next_index; 2668 i = next_index;
2669 last = i + 1; 2669 last = i + 1;
2670 break; 2670 break;
2671 case '\'': 2671 case '\'':
2672 if (i > last) { 2672 if (i > last) {
2673 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone); 2673 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2674 } 2674 }
2675 parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone); 2675 parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
2676 i = next_index; 2676 i = next_index;
2677 last = i + 1; 2677 last = i + 1;
2678 break; 2678 break;
2679 case '&': 2679 case '&':
2680 if (i > last) { 2680 if (i > last) {
2681 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone); 2681 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2682 } 2682 }
2683 parts->Add(ReplacementPart::SubjectMatch(), zone); 2683 parts->Add(ReplacementPart::SubjectMatch(), zone);
2684 i = next_index; 2684 i = next_index;
2685 last = i + 1; 2685 last = i + 1;
2686 break; 2686 break;
2687 case '0': 2687 case '0':
2688 case '1': 2688 case '1':
2689 case '2': 2689 case '2':
2690 case '3': 2690 case '3':
2691 case '4': 2691 case '4':
2692 case '5': 2692 case '5':
2693 case '6': 2693 case '6':
2694 case '7': 2694 case '7':
2695 case '8': 2695 case '8':
2696 case '9': { 2696 case '9': {
2697 int capture_ref = c2 - '0'; 2697 int capture_ref = c2 - '0';
2698 if (capture_ref > capture_count) { 2698 if (capture_ref > capture_count) {
2699 i = next_index; 2699 i = next_index;
2700 continue; 2700 continue;
2701 } 2701 }
2702 int second_digit_index = next_index + 1; 2702 int second_digit_index = next_index + 1;
2703 if (second_digit_index < length) { 2703 if (second_digit_index < length) {
2704 // Peek ahead to see if we have two digits. 2704 // Peek ahead to see if we have two digits.
2705 Char c3 = characters[second_digit_index]; 2705 Char c3 = characters[second_digit_index];
2706 if ('0' <= c3 && c3 <= '9') { // Double digits. 2706 if ('0' <= c3 && c3 <= '9') { // Double digits.
2707 int double_digit_ref = capture_ref * 10 + c3 - '0'; 2707 int double_digit_ref = capture_ref * 10 + c3 - '0';
2708 if (double_digit_ref <= capture_count) { 2708 if (double_digit_ref <= capture_count) {
2709 next_index = second_digit_index; 2709 next_index = second_digit_index;
2710 capture_ref = double_digit_ref; 2710 capture_ref = double_digit_ref;
2711 } 2711 }
2712 } 2712 }
2713 } 2713 }
2714 if (capture_ref > 0) { 2714 if (capture_ref > 0) {
2715 if (i > last) { 2715 if (i > last) {
2716 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone); 2716 parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
2717 } 2717 }
2718 ASSERT(capture_ref <= capture_count); 2718 ASSERT(capture_ref <= capture_count);
2719 parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone); 2719 parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
2720 last = next_index + 1; 2720 last = next_index + 1;
2721 } 2721 }
2722 i = next_index; 2722 i = next_index;
2723 break; 2723 break;
2724 } 2724 }
2725 default: 2725 default:
2726 i = next_index; 2726 i = next_index;
2727 break; 2727 break;
2728 } 2728 }
2729 } 2729 }
2730 } 2730 }
2731 if (length > last) { 2731 if (length > last) {
2732 if (last == 0) { 2732 if (last == 0) {
2733 // Replacement is simple. Do not use Apply to do the replacement. 2733 // Replacement is simple. Do not use Apply to do the replacement.
2734 return true; 2734 return true;
2735 } else { 2735 } else {
2736 parts->Add(ReplacementPart::ReplacementSubString(last, length), zone); 2736 parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
2737 } 2737 }
2738 } 2738 }
2739 return false; 2739 return false;
2740 } 2740 }
2741 2741
2742 ZoneList<ReplacementPart> parts_; 2742 ZoneList<ReplacementPart> parts_;
2743 ZoneList<Handle<String> > replacement_substrings_; 2743 ZoneList<Handle<String> > replacement_substrings_;
2744 Zone* zone_; 2744 Zone* zone_;
2745 }; 2745 };
2746 2746
2747 2747
2748 bool CompiledReplacement::Compile(Handle<String> replacement, 2748 bool CompiledReplacement::Compile(Handle<String> replacement,
2749 int capture_count, 2749 int capture_count,
2750 int subject_length) { 2750 int subject_length) {
2751 { 2751 {
2752 AssertNoAllocation no_alloc; 2752 AssertNoAllocation no_alloc;
2753 String::FlatContent content = replacement->GetFlatContent(); 2753 String::FlatContent content = replacement->GetFlatContent();
2754 ASSERT(content.IsFlat()); 2754 ASSERT(content.IsFlat());
2755 bool simple = false; 2755 bool simple = false;
2756 if (content.IsAscii()) { 2756 if (content.IsAscii()) {
2757 simple = ParseReplacementPattern(&parts_, 2757 simple = ParseReplacementPattern(&parts_,
2758 content.ToAsciiVector(), 2758 content.ToAsciiVector(),
2759 capture_count, 2759 capture_count,
2760 subject_length, 2760 subject_length,
2761 zone()); 2761 zone());
2762 } else { 2762 } else {
2763 ASSERT(content.IsTwoByte()); 2763 ASSERT(content.IsTwoByte());
2764 simple = ParseReplacementPattern(&parts_, 2764 simple = ParseReplacementPattern(&parts_,
2765 content.ToUC16Vector(), 2765 content.ToUC16Vector(),
2766 capture_count, 2766 capture_count,
2767 subject_length, 2767 subject_length,
2768 zone()); 2768 zone());
2769 } 2769 }
2770 if (simple) return true; 2770 if (simple) return true;
2771 } 2771 }
2772 2772
2773 Isolate* isolate = replacement->GetIsolate(); 2773 Isolate* isolate = replacement->GetIsolate();
2774 // Find substrings of replacement string and create them as String objects. 2774 // Find substrings of replacement string and create them as String objects.
2775 int substring_index = 0; 2775 int substring_index = 0;
2776 for (int i = 0, n = parts_.length(); i < n; i++) { 2776 for (int i = 0, n = parts_.length(); i < n; i++) {
2777 int tag = parts_[i].tag; 2777 int tag = parts_[i].tag;
2778 if (tag <= 0) { // A replacement string slice. 2778 if (tag <= 0) { // A replacement string slice.
2779 int from = -tag; 2779 int from = -tag;
2780 int to = parts_[i].data; 2780 int to = parts_[i].data;
2781 replacement_substrings_.Add( 2781 replacement_substrings_.Add(
2782 isolate->factory()->NewSubString(replacement, from, to), zone()); 2782 isolate->factory()->NewSubString(replacement, from, to), zone());
2783 parts_[i].tag = REPLACEMENT_SUBSTRING; 2783 parts_[i].tag = REPLACEMENT_SUBSTRING;
2784 parts_[i].data = substring_index; 2784 parts_[i].data = substring_index;
2785 substring_index++; 2785 substring_index++;
2786 } else if (tag == REPLACEMENT_STRING) { 2786 } else if (tag == REPLACEMENT_STRING) {
2787 replacement_substrings_.Add(replacement, zone()); 2787 replacement_substrings_.Add(replacement, zone());
2788 parts_[i].data = substring_index; 2788 parts_[i].data = substring_index;
2789 substring_index++; 2789 substring_index++;
2790 } 2790 }
2791 } 2791 }
2792 return false; 2792 return false;
2793 } 2793 }
2794 2794
2795 2795
2796 void CompiledReplacement::Apply(ReplacementStringBuilder* builder, 2796 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
2797 int match_from, 2797 int match_from,
2798 int match_to, 2798 int match_to,
2799 int32_t* match) { 2799 int32_t* match) {
2800 ASSERT_LT(0, parts_.length()); 2800 ASSERT_LT(0, parts_.length());
2801 for (int i = 0, n = parts_.length(); i < n; i++) { 2801 for (int i = 0, n = parts_.length(); i < n; i++) {
2802 ReplacementPart part = parts_[i]; 2802 ReplacementPart part = parts_[i];
2803 switch (part.tag) { 2803 switch (part.tag) {
2804 case SUBJECT_PREFIX: 2804 case SUBJECT_PREFIX:
2805 if (match_from > 0) builder->AddSubjectSlice(0, match_from); 2805 if (match_from > 0) builder->AddSubjectSlice(0, match_from);
2806 break; 2806 break;
2807 case SUBJECT_SUFFIX: { 2807 case SUBJECT_SUFFIX: {
2808 int subject_length = part.data; 2808 int subject_length = part.data;
2809 if (match_to < subject_length) { 2809 if (match_to < subject_length) {
2810 builder->AddSubjectSlice(match_to, subject_length); 2810 builder->AddSubjectSlice(match_to, subject_length);
2811 } 2811 }
2812 break; 2812 break;
2813 } 2813 }
2814 case SUBJECT_CAPTURE: { 2814 case SUBJECT_CAPTURE: {
2815 int capture = part.data; 2815 int capture = part.data;
2816 int from = match[capture * 2]; 2816 int from = match[capture * 2];
2817 int to = match[capture * 2 + 1]; 2817 int to = match[capture * 2 + 1];
2818 if (from >= 0 && to > from) { 2818 if (from >= 0 && to > from) {
2819 builder->AddSubjectSlice(from, to); 2819 builder->AddSubjectSlice(from, to);
2820 } 2820 }
2821 break; 2821 break;
2822 } 2822 }
2823 case REPLACEMENT_SUBSTRING: 2823 case REPLACEMENT_SUBSTRING:
2824 case REPLACEMENT_STRING: 2824 case REPLACEMENT_STRING:
2825 builder->AddString(replacement_substrings_[part.data]); 2825 builder->AddString(replacement_substrings_[part.data]);
2826 break; 2826 break;
2827 default: 2827 default:
2828 UNREACHABLE(); 2828 UNREACHABLE();
2829 } 2829 }
2830 } 2830 }
2831 } 2831 }
2832 2832
2833 2833
2834 void FindAsciiStringIndices(Vector<const char> subject, 2834 void FindAsciiStringIndices(Vector<const char> subject,
2835 char pattern, 2835 char pattern,
2836 ZoneList<int>* indices, 2836 ZoneList<int>* indices,
2837 unsigned int limit, 2837 unsigned int limit,
2838 Zone* zone) { 2838 Zone* zone) {
2839 ASSERT(limit > 0); 2839 ASSERT(limit > 0);
2840 // Collect indices of pattern in subject using memchr. 2840 // Collect indices of pattern in subject using memchr.
2841 // Stop after finding at most limit values. 2841 // Stop after finding at most limit values.
2842 const char* subject_start = reinterpret_cast<const char*>(subject.start()); 2842 const char* subject_start = reinterpret_cast<const char*>(subject.start());
2843 const char* subject_end = subject_start + subject.length(); 2843 const char* subject_end = subject_start + subject.length();
2844 const char* pos = subject_start; 2844 const char* pos = subject_start;
2845 while (limit > 0) { 2845 while (limit > 0) {
2846 pos = reinterpret_cast<const char*>( 2846 pos = reinterpret_cast<const char*>(
2847 memchr(pos, pattern, subject_end - pos)); 2847 memchr(pos, pattern, subject_end - pos));
2848 if (pos == NULL) return; 2848 if (pos == NULL) return;
2849 indices->Add(static_cast<int>(pos - subject_start), zone); 2849 indices->Add(static_cast<int>(pos - subject_start), zone);
2850 pos++; 2850 pos++;
2851 limit--; 2851 limit--;
2852 } 2852 }
2853 } 2853 }
2854 2854
2855 2855
2856 template <typename SubjectChar, typename PatternChar> 2856 template <typename SubjectChar, typename PatternChar>
2857 void FindStringIndices(Isolate* isolate, 2857 void FindStringIndices(Isolate* isolate,
2858 Vector<const SubjectChar> subject, 2858 Vector<const SubjectChar> subject,
2859 Vector<const PatternChar> pattern, 2859 Vector<const PatternChar> pattern,
2860 ZoneList<int>* indices, 2860 ZoneList<int>* indices,
2861 unsigned int limit, 2861 unsigned int limit,
2862 Zone* zone) { 2862 Zone* zone) {
2863 ASSERT(limit > 0); 2863 ASSERT(limit > 0);
2864 // Collect indices of pattern in subject. 2864 // Collect indices of pattern in subject.
2865 // Stop after finding at most limit values. 2865 // Stop after finding at most limit values.
2866 int pattern_length = pattern.length(); 2866 int pattern_length = pattern.length();
2867 int index = 0; 2867 int index = 0;
2868 StringSearch<PatternChar, SubjectChar> search(isolate, pattern); 2868 StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
2869 while (limit > 0) { 2869 while (limit > 0) {
2870 index = search.Search(subject, index); 2870 index = search.Search(subject, index);
2871 if (index < 0) return; 2871 if (index < 0) return;
2872 indices->Add(index, zone); 2872 indices->Add(index, zone);
2873 index += pattern_length; 2873 index += pattern_length;
2874 limit--; 2874 limit--;
2875 } 2875 }
2876 } 2876 }
2877 2877
2878 2878
2879 void FindStringIndicesDispatch(Isolate* isolate, 2879 void FindStringIndicesDispatch(Isolate* isolate,
2880 String* subject, 2880 String* subject,
2881 String* pattern, 2881 String* pattern,
2882 ZoneList<int>* indices, 2882 ZoneList<int>* indices,
2883 unsigned int limit, 2883 unsigned int limit,
2884 Zone* zone) { 2884 Zone* zone) {
2885 { 2885 {
2886 AssertNoAllocation no_gc; 2886 AssertNoAllocation no_gc;
2887 String::FlatContent subject_content = subject->GetFlatContent(); 2887 String::FlatContent subject_content = subject->GetFlatContent();
2888 String::FlatContent pattern_content = pattern->GetFlatContent(); 2888 String::FlatContent pattern_content = pattern->GetFlatContent();
2889 ASSERT(subject_content.IsFlat()); 2889 ASSERT(subject_content.IsFlat());
2890 ASSERT(pattern_content.IsFlat()); 2890 ASSERT(pattern_content.IsFlat());
2891 if (subject_content.IsAscii()) { 2891 if (subject_content.IsAscii()) {
2892 Vector<const char> subject_vector = subject_content.ToAsciiVector(); 2892 Vector<const char> subject_vector = subject_content.ToAsciiVector();
2893 if (pattern_content.IsAscii()) { 2893 if (pattern_content.IsAscii()) {
2894 Vector<const char> pattern_vector = pattern_content.ToAsciiVector(); 2894 Vector<const char> pattern_vector = pattern_content.ToAsciiVector();
2895 if (pattern_vector.length() == 1) { 2895 if (pattern_vector.length() == 1) {
2896 FindAsciiStringIndices(subject_vector, 2896 FindAsciiStringIndices(subject_vector,
2897 pattern_vector[0], 2897 pattern_vector[0],
2898 indices, 2898 indices,
2899 limit, 2899 limit,
2900 zone); 2900 zone);
2901 } else { 2901 } else {
2902 FindStringIndices(isolate, 2902 FindStringIndices(isolate,
2903 subject_vector, 2903 subject_vector,
2904 pattern_vector, 2904 pattern_vector,
2905 indices, 2905 indices,
2906 limit, 2906 limit,
2907 zone); 2907 zone);
2908 } 2908 }
2909 } else { 2909 } else {
2910 FindStringIndices(isolate, 2910 FindStringIndices(isolate,
2911 subject_vector, 2911 subject_vector,
2912 pattern_content.ToUC16Vector(), 2912 pattern_content.ToUC16Vector(),
2913 indices, 2913 indices,
2914 limit, 2914 limit,
2915 zone); 2915 zone);
2916 } 2916 }
2917 } else { 2917 } else {
2918 Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); 2918 Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
2919 if (pattern_content.IsAscii()) { 2919 if (pattern_content.IsAscii()) {
2920 FindStringIndices(isolate, 2920 FindStringIndices(isolate,
2921 subject_vector, 2921 subject_vector,
2922 pattern_content.ToAsciiVector(), 2922 pattern_content.ToAsciiVector(),
2923 indices, 2923 indices,
2924 limit, 2924 limit,
2925 zone); 2925 zone);
2926 } else { 2926 } else {
2927 FindStringIndices(isolate, 2927 FindStringIndices(isolate,
2928 subject_vector, 2928 subject_vector,
2929 pattern_content.ToUC16Vector(), 2929 pattern_content.ToUC16Vector(),
2930 indices, 2930 indices,
2931 limit, 2931 limit,
2932 zone); 2932 zone);
2933 } 2933 }
2934 } 2934 }
2935 } 2935 }
2936 } 2936 }
2937 2937
2938 2938
2939 template<typename ResultSeqString> 2939 template<typename ResultSeqString>
2940 MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString( 2940 MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString(
2941 Isolate* isolate, 2941 Isolate* isolate,
2942 Handle<String> subject, 2942 Handle<String> subject,
2943 Handle<JSRegExp> pattern_regexp, 2943 Handle<JSRegExp> pattern_regexp,
2944 Handle<String> replacement, 2944 Handle<String> replacement,
2945 Handle<JSArray> last_match_info) { 2945 Handle<JSArray> last_match_info) {
2946 ASSERT(subject->IsFlat()); 2946 ASSERT(subject->IsFlat());
2947 ASSERT(replacement->IsFlat()); 2947 ASSERT(replacement->IsFlat());
2948 2948
2949 Zone* zone = isolate->runtime_zone(); 2949 Zone* zone = isolate->runtime_zone();
2950 ZoneScope zone_space(zone, DELETE_ON_EXIT); 2950 ZoneScope zone_space(zone, DELETE_ON_EXIT);
2951 ZoneList<int> indices(8, zone); 2951 ZoneList<int> indices(8, zone);
2952 ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag()); 2952 ASSERT_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
2953 String* pattern = 2953 String* pattern =
2954 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex)); 2954 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
2955 int subject_len = subject->length(); 2955 int subject_len = subject->length();
2956 int pattern_len = pattern->length(); 2956 int pattern_len = pattern->length();
2957 int replacement_len = replacement->length(); 2957 int replacement_len = replacement->length();
2958 2958
2959 FindStringIndicesDispatch( 2959 FindStringIndicesDispatch(
2960 isolate, *subject, pattern, &indices, 0xffffffff, zone); 2960 isolate, *subject, pattern, &indices, 0xffffffff, zone);
2961 2961
2962 int matches = indices.length(); 2962 int matches = indices.length();
2963 if (matches == 0) return *subject; 2963 if (matches == 0) return *subject;
2964 2964
2965 // Detect integer overflow. 2965 // Detect integer overflow.
2966 int64_t result_len_64 = 2966 int64_t result_len_64 =
2967 (static_cast<int64_t>(replacement_len) - 2967 (static_cast<int64_t>(replacement_len) -
2968 static_cast<int64_t>(pattern_len)) * 2968 static_cast<int64_t>(pattern_len)) *
2969 static_cast<int64_t>(matches) + 2969 static_cast<int64_t>(matches) +
2970 static_cast<int64_t>(subject_len); 2970 static_cast<int64_t>(subject_len);
2971 if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException(); 2971 if (result_len_64 > INT_MAX) return Failure::OutOfMemoryException();
2972 int result_len = static_cast<int>(result_len_64); 2972 int result_len = static_cast<int>(result_len_64);
2973 2973
2974 int subject_pos = 0; 2974 int subject_pos = 0;
2975 int result_pos = 0; 2975 int result_pos = 0;
2976 2976
2977 Handle<ResultSeqString> result; 2977 Handle<ResultSeqString> result;
2978 if (ResultSeqString::kHasAsciiEncoding) { 2978 if (ResultSeqString::kHasAsciiEncoding) {
2979 result = Handle<ResultSeqString>::cast( 2979 result = Handle<ResultSeqString>::cast(
2980 isolate->factory()->NewRawAsciiString(result_len)); 2980 isolate->factory()->NewRawAsciiString(result_len));
2981 } else { 2981 } else {
2982 result = Handle<ResultSeqString>::cast( 2982 result = Handle<ResultSeqString>::cast(
2983 isolate->factory()->NewRawTwoByteString(result_len)); 2983 isolate->factory()->NewRawTwoByteString(result_len));
2984 } 2984 }
2985 2985
2986 for (int i = 0; i < matches; i++) { 2986 for (int i = 0; i < matches; i++) {
2987 // Copy non-matched subject content. 2987 // Copy non-matched subject content.
2988 if (subject_pos < indices.at(i)) { 2988 if (subject_pos < indices.at(i)) {
2989 String::WriteToFlat(*subject, 2989 String::WriteToFlat(*subject,
2990 result->GetChars() + result_pos, 2990 result->GetChars() + result_pos,
2991 subject_pos, 2991 subject_pos,
2992 indices.at(i)); 2992 indices.at(i));
2993 result_pos += indices.at(i) - subject_pos; 2993 result_pos += indices.at(i) - subject_pos;
2994 } 2994 }
2995 2995
2996 // Replace match. 2996 // Replace match.
2997 if (replacement_len > 0) { 2997 if (replacement_len > 0) {
2998 String::WriteToFlat(*replacement, 2998 String::WriteToFlat(*replacement,
2999 result->GetChars() + result_pos, 2999 result->GetChars() + result_pos,
3000 0, 3000 0,
3001 replacement_len); 3001 replacement_len);
3002 result_pos += replacement_len; 3002 result_pos += replacement_len;
3003 } 3003 }
3004 3004
3005 subject_pos = indices.at(i) + pattern_len; 3005 subject_pos = indices.at(i) + pattern_len;
3006 } 3006 }
3007 // Add remaining subject content at the end. 3007 // Add remaining subject content at the end.
3008 if (subject_pos < subject_len) { 3008 if (subject_pos < subject_len) {
3009 String::WriteToFlat(*subject, 3009 String::WriteToFlat(*subject,
3010 result->GetChars() + result_pos, 3010 result->GetChars() + result_pos,
3011 subject_pos, 3011 subject_pos,
3012 subject_len); 3012 subject_len);
3013 } 3013 }
3014 3014
3015 int32_t match_indices[] = { indices.at(matches - 1), 3015 int32_t match_indices[] = { indices.at(matches - 1),
3016 indices.at(matches - 1) + pattern_len }; 3016 indices.at(matches - 1) + pattern_len };
3017 RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices); 3017 RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
3018 3018
3019 return *result; 3019 return *result;
3020 } 3020 }
3021 3021
3022 3022
3023 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString( 3023 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
3024 Isolate* isolate, 3024 Isolate* isolate,
3025 Handle<String> subject, 3025 Handle<String> subject,
3026 Handle<JSRegExp> regexp, 3026 Handle<JSRegExp> regexp,
3027 Handle<String> replacement, 3027 Handle<String> replacement,
3028 Handle<JSArray> last_match_info) { 3028 Handle<JSArray> last_match_info) {
3029 ASSERT(subject->IsFlat()); 3029 ASSERT(subject->IsFlat());
3030 ASSERT(replacement->IsFlat()); 3030 ASSERT(replacement->IsFlat());
3031 3031
3032 bool is_global = regexp->GetFlags().is_global(); 3032 bool is_global = regexp->GetFlags().is_global();
3033 int capture_count = regexp->CaptureCount(); 3033 int capture_count = regexp->CaptureCount();
3034 int subject_length = subject->length(); 3034 int subject_length = subject->length();
3035 3035
3036 // CompiledReplacement uses zone allocation. 3036 // CompiledReplacement uses zone allocation.
3037 Zone* zone = isolate->runtime_zone(); 3037 Zone* zone = isolate->runtime_zone();
3038 ZoneScope zonescope(zone, DELETE_ON_EXIT); 3038 ZoneScope zonescope(zone, DELETE_ON_EXIT);
3039 CompiledReplacement compiled_replacement(zone); 3039 CompiledReplacement compiled_replacement(zone);
3040 bool simple_replace = compiled_replacement.Compile(replacement, 3040 bool simple_replace = compiled_replacement.Compile(replacement,
3041 capture_count, 3041 capture_count,
3042 subject_length); 3042 subject_length);
3043 3043
3044 // Shortcut for simple non-regexp global replacements 3044 // Shortcut for simple non-regexp global replacements
3045 if (is_global && 3045 if (is_global &&
3046 regexp->TypeTag() == JSRegExp::ATOM && 3046 regexp->TypeTag() == JSRegExp::ATOM &&
3047 simple_replace) { 3047 simple_replace) {
3048 if (subject->HasOnlyAsciiChars() && replacement->HasOnlyAsciiChars()) { 3048 if (subject->HasOnlyAsciiChars() && replacement->HasOnlyAsciiChars()) {
3049 return StringReplaceAtomRegExpWithString<SeqAsciiString>( 3049 return StringReplaceAtomRegExpWithString<SeqAsciiString>(
3050 isolate, subject, regexp, replacement, last_match_info); 3050 isolate, subject, regexp, replacement, last_match_info);
3051 } else { 3051 } else {
3052 return StringReplaceAtomRegExpWithString<SeqTwoByteString>( 3052 return StringReplaceAtomRegExpWithString<SeqTwoByteString>(
3053 isolate, subject, regexp, replacement, last_match_info); 3053 isolate, subject, regexp, replacement, last_match_info);
3054 } 3054 }
3055 } 3055 }
3056 3056
3057 RegExpImpl::GlobalCache global_cache(regexp, subject, is_global, isolate); 3057 RegExpImpl::GlobalCache global_cache(regexp, subject, is_global, isolate);
3058 if (global_cache.HasException()) return Failure::Exception(); 3058 if (global_cache.HasException()) return Failure::Exception();
3059 3059
3060 int32_t* current_match = global_cache.FetchNext(); 3060 int32_t* current_match = global_cache.FetchNext();
3061 if (current_match == NULL) { 3061 if (current_match == NULL) {
3062 if (global_cache.HasException()) return Failure::Exception(); 3062 if (global_cache.HasException()) return Failure::Exception();
3063 return *subject; 3063 return *subject;
3064 } 3064 }
3065 3065
3066 // Guessing the number of parts that the final result string is built 3066 // Guessing the number of parts that the final result string is built
3067 // from. Global regexps can match any number of times, so we guess 3067 // from. Global regexps can match any number of times, so we guess
3068 // conservatively. 3068 // conservatively.
3069 int expected_parts = 3069 int expected_parts =
3070 (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1; 3070 (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
3071 ReplacementStringBuilder builder(isolate->heap(), 3071 ReplacementStringBuilder builder(isolate->heap(),
3072 subject, 3072 subject,
3073 expected_parts); 3073 expected_parts);
3074 3074
3075 // Number of parts added by compiled replacement plus preceeding 3075 // Number of parts added by compiled replacement plus preceeding
3076 // string and possibly suffix after last match. It is possible for 3076 // string and possibly suffix after last match. It is possible for
3077 // all components to use two elements when encoded as two smis. 3077 // all components to use two elements when encoded as two smis.
3078 const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2); 3078 const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
3079 3079
3080 int prev = 0; 3080 int prev = 0;
3081 3081
3082 do { 3082 do {
3083 builder.EnsureCapacity(parts_added_per_loop); 3083 builder.EnsureCapacity(parts_added_per_loop);
3084 3084
3085 int start = current_match[0]; 3085 int start = current_match[0];
3086 int end = current_match[1]; 3086 int end = current_match[1];
3087 3087
3088 if (prev < start) { 3088 if (prev < start) {
3089 builder.AddSubjectSlice(prev, start); 3089 builder.AddSubjectSlice(prev, start);
3090 } 3090 }
3091 3091
3092 if (simple_replace) { 3092 if (simple_replace) {
3093 builder.AddString(replacement); 3093 builder.AddString(replacement);
3094 } else { 3094 } else {
3095 compiled_replacement.Apply(&builder, 3095 compiled_replacement.Apply(&builder,
3096 start, 3096 start,
3097 end, 3097 end,
3098 current_match); 3098 current_match);
3099 } 3099 }
3100 prev = end; 3100 prev = end;
3101 3101
3102 // Only continue checking for global regexps. 3102 // Only continue checking for global regexps.
3103 if (!is_global) break; 3103 if (!is_global) break;
3104 3104
3105 current_match = global_cache.FetchNext(); 3105 current_match = global_cache.FetchNext();
3106 } while (current_match != NULL); 3106 } while (current_match != NULL);
3107 3107
3108 if (global_cache.HasException()) return Failure::Exception(); 3108 if (global_cache.HasException()) return Failure::Exception();
3109 3109
3110 if (prev < subject_length) { 3110 if (prev < subject_length) {
3111 builder.EnsureCapacity(2); 3111 builder.EnsureCapacity(2);
3112 builder.AddSubjectSlice(prev, subject_length); 3112 builder.AddSubjectSlice(prev, subject_length);
3113 } 3113 }
3114 3114
3115 RegExpImpl::SetLastMatchInfo(last_match_info, 3115 RegExpImpl::SetLastMatchInfo(last_match_info,
3116 subject, 3116 subject,
3117 capture_count, 3117 capture_count,
3118 global_cache.LastSuccessfulMatch()); 3118 global_cache.LastSuccessfulMatch());
3119 3119
3120 return *(builder.ToString()); 3120 return *(builder.ToString());
3121 } 3121 }
3122 3122
3123 3123
3124 template <typename ResultSeqString> 3124 template <typename ResultSeqString>
3125 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString( 3125 MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
3126 Isolate* isolate, 3126 Isolate* isolate,
3127 Handle<String> subject, 3127 Handle<String> subject,
3128 Handle<JSRegExp> regexp, 3128 Handle<JSRegExp> regexp,
3129 Handle<JSArray> last_match_info) { 3129 Handle<JSArray> last_match_info) {
3130 ASSERT(subject->IsFlat()); 3130 ASSERT(subject->IsFlat());
3131 3131
3132 bool is_global = regexp->GetFlags().is_global(); 3132 bool is_global = regexp->GetFlags().is_global();
3133 3133
3134 // Shortcut for simple non-regexp global replacements 3134 // Shortcut for simple non-regexp global replacements
3135 if (is_global && 3135 if (is_global &&
3136 regexp->TypeTag() == JSRegExp::ATOM) { 3136 regexp->TypeTag() == JSRegExp::ATOM) {
3137 Handle<String> empty_string(HEAP->empty_string()); 3137 Handle<String> empty_string(HEAP->empty_string());
3138 if (subject->HasOnlyAsciiChars()) { 3138 if (subject->HasOnlyAsciiChars()) {
3139 return StringReplaceAtomRegExpWithString<SeqAsciiString>( 3139 return StringReplaceAtomRegExpWithString<SeqAsciiString>(
3140 isolate, 3140 isolate,
3141 subject, 3141 subject,
3142 regexp, 3142 regexp,
3143 empty_string, 3143 empty_string,
3144 last_match_info); 3144 last_match_info);
3145 } else { 3145 } else {
3146 return StringReplaceAtomRegExpWithString<SeqTwoByteString>( 3146 return StringReplaceAtomRegExpWithString<SeqTwoByteString>(
3147 isolate, 3147 isolate,
3148 subject, 3148 subject,
3149 regexp, 3149 regexp,
3150 empty_string, 3150 empty_string,
3151 last_match_info); 3151 last_match_info);
3152 } 3152 }
3153 } 3153 }
3154 3154
3155 RegExpImpl::GlobalCache global_cache(regexp, subject, is_global, isolate); 3155 RegExpImpl::GlobalCache global_cache(regexp, subject, is_global, isolate);
3156 if (global_cache.HasException()) return Failure::Exception(); 3156 if (global_cache.HasException()) return Failure::Exception();
3157 3157
3158 int32_t* current_match = global_cache.FetchNext(); 3158 int32_t* current_match = global_cache.FetchNext();
3159 if (current_match == NULL) { 3159 if (current_match == NULL) {
3160 if (global_cache.HasException()) return Failure::Exception(); 3160 if (global_cache.HasException()) return Failure::Exception();
3161 return *subject; 3161 return *subject;
3162 } 3162 }
3163 3163
3164 int start = current_match[0]; 3164 int start = current_match[0];
3165 int end = current_match[1]; 3165 int end = current_match[1];
3166 int capture_count = regexp->CaptureCount(); 3166 int capture_count = regexp->CaptureCount();
3167 int subject_length = subject->length(); 3167 int subject_length = subject->length();
3168 3168
3169 int new_length = subject_length - (end - start); 3169 int new_length = subject_length - (end - start);
3170 if (new_length == 0) return isolate->heap()->empty_string(); 3170 if (new_length == 0) return isolate->heap()->empty_string();
3171 3171
3172 Handle<ResultSeqString> answer; 3172 Handle<ResultSeqString> answer;
3173 if (ResultSeqString::kHasAsciiEncoding) { 3173 if (ResultSeqString::kHasAsciiEncoding) {
3174 answer = Handle<ResultSeqString>::cast( 3174 answer = Handle<ResultSeqString>::cast(
3175 isolate->factory()->NewRawAsciiString(new_length)); 3175 isolate->factory()->NewRawAsciiString(new_length));
3176 } else { 3176 } else {
3177 answer = Handle<ResultSeqString>::cast( 3177 answer = Handle<ResultSeqString>::cast(
3178 isolate->factory()->NewRawTwoByteString(new_length)); 3178 isolate->factory()->NewRawTwoByteString(new_length));
3179 } 3179 }
3180 3180
3181 if (!is_global) { 3181 if (!is_global) {
3182 RegExpImpl::SetLastMatchInfo( 3182 RegExpImpl::SetLastMatchInfo(
3183 last_match_info, subject, capture_count, current_match); 3183 last_match_info, subject, capture_count, current_match);
3184 if (start == end) { 3184 if (start == end) {
3185 return *subject; 3185 return *subject;
3186 } else { 3186 } else {
3187 if (start > 0) { 3187 if (start > 0) {
3188 String::WriteToFlat(*subject, answer->GetChars(), 0, start); 3188 String::WriteToFlat(*subject, answer->GetChars(), 0, start);
3189 } 3189 }
3190 if (end < subject_length) { 3190 if (end < subject_length) {
3191 String::WriteToFlat( 3191 String::WriteToFlat(
3192 *subject, answer->GetChars() + start, end, subject_length); 3192 *subject, answer->GetChars() + start, end, subject_length);
3193 } 3193 }
3194 return *answer; 3194 return *answer;
3195 } 3195 }
3196 } 3196 }
3197 3197
3198 int prev = 0; 3198 int prev = 0;
3199 int position = 0; 3199 int position = 0;
3200 3200
3201 do { 3201 do {
3202 start = current_match[0]; 3202 start = current_match[0];
3203 end = current_match[1]; 3203 end = current_match[1];
3204 if (prev < start) { 3204 if (prev < start) {
3205 // Add substring subject[prev;start] to answer string. 3205 // Add substring subject[prev;start] to answer string.
3206 String::WriteToFlat( 3206 String::WriteToFlat(
3207 *subject, answer->GetChars() + position, prev, start); 3207 *subject, answer->GetChars() + position, prev, start);
3208 position += start - prev; 3208 position += start - prev;
3209 } 3209 }
3210 prev = end; 3210 prev = end;
3211 3211
3212 current_match = global_cache.FetchNext(); 3212 current_match = global_cache.FetchNext();
3213 } while (current_match != NULL); 3213 } while (current_match != NULL);
3214 3214
3215 if (global_cache.HasException()) return Failure::Exception(); 3215 if (global_cache.HasException()) return Failure::Exception();
3216 3216
3217 RegExpImpl::SetLastMatchInfo(last_match_info, 3217 RegExpImpl::SetLastMatchInfo(last_match_info,
3218 subject, 3218 subject,
3219 capture_count, 3219 capture_count,
3220 global_cache.LastSuccessfulMatch()); 3220 global_cache.LastSuccessfulMatch());
3221 3221
3222 if (prev < subject_length) { 3222 if (prev < subject_length) {
3223 // Add substring subject[prev;length] to answer string. 3223 // Add substring subject[prev;length] to answer string.
3224 String::WriteToFlat( 3224 String::WriteToFlat(
3225 *subject, answer->GetChars() + position, prev, subject_length); 3225 *subject, answer->GetChars() + position, prev, subject_length);
3226 position += subject_length - prev; 3226 position += subject_length - prev;
3227 } 3227 }
3228 3228
3229 if (position == 0) return isolate->heap()->empty_string(); 3229 if (position == 0) return isolate->heap()->empty_string();
3230 3230
3231 // Shorten string and fill 3231 // Shorten string and fill
3232 int string_size = ResultSeqString::SizeFor(position); 3232 int string_size = ResultSeqString::SizeFor(position);
3233 int allocated_string_size = ResultSeqString::SizeFor(new_length); 3233 int allocated_string_size = ResultSeqString::SizeFor(new_length);
3234 int delta = allocated_string_size - string_size; 3234 int delta = allocated_string_size - string_size;
3235 3235
3236 answer->set_length(position); 3236 answer->set_length(position);
3237 if (delta == 0) return *answer; 3237 if (delta == 0) return *answer;
3238 3238
3239 Address end_of_string = answer->address() + string_size; 3239 Address end_of_string = answer->address() + string_size;
3240 isolate->heap()->CreateFillerObjectAt(end_of_string, delta); 3240 isolate->heap()->CreateFillerObjectAt(end_of_string, delta);
3241 if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) { 3241 if (Marking::IsBlack(Marking::MarkBitFrom(*answer))) {
3242 MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta); 3242 MemoryChunk::IncrementLiveBytesFromMutator(answer->address(), -delta);
3243 } 3243 }
3244 3244
3245 return *answer; 3245 return *answer;
3246 } 3246 }
3247 3247
3248 3248
3249 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) { 3249 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
3250 ASSERT(args.length() == 4); 3250 ASSERT(args.length() == 4);
3251 3251
3252 HandleScope scope(isolate); 3252 HandleScope scope(isolate);
3253 3253
3254 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); 3254 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3255 CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2); 3255 CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
3256 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); 3256 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
3257 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3); 3257 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 3);
3258 3258
3259 if (!subject->IsFlat()) subject = FlattenGetString(subject); 3259 if (!subject->IsFlat()) subject = FlattenGetString(subject);
3260 3260
3261 if (!replacement->IsFlat()) replacement = FlattenGetString(replacement); 3261 if (!replacement->IsFlat()) replacement = FlattenGetString(replacement);
3262 3262
3263 ASSERT(last_match_info->HasFastObjectElements()); 3263 ASSERT(last_match_info->HasFastObjectElements());
3264 3264
3265 if (replacement->length() == 0) { 3265 if (replacement->length() == 0) {
3266 if (subject->HasOnlyAsciiChars()) { 3266 if (subject->HasOnlyAsciiChars()) {
3267 return StringReplaceRegExpWithEmptyString<SeqAsciiString>( 3267 return StringReplaceRegExpWithEmptyString<SeqAsciiString>(
3268 isolate, subject, regexp, last_match_info); 3268 isolate, subject, regexp, last_match_info);
3269 } else { 3269 } else {
3270 return StringReplaceRegExpWithEmptyString<SeqTwoByteString>( 3270 return StringReplaceRegExpWithEmptyString<SeqTwoByteString>(
3271 isolate, subject, regexp, last_match_info); 3271 isolate, subject, regexp, last_match_info);
3272 } 3272 }
3273 } 3273 }
3274 3274
3275 return StringReplaceRegExpWithString( 3275 return StringReplaceRegExpWithString(
3276 isolate, subject, regexp, replacement, last_match_info); 3276 isolate, subject, regexp, replacement, last_match_info);
3277 } 3277 }
3278 3278
3279 3279
3280 Handle<String> StringReplaceOneCharWithString(Isolate* isolate, 3280 Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
3281 Handle<String> subject, 3281 Handle<String> subject,
3282 Handle<String> search, 3282 Handle<String> search,
3283 Handle<String> replace, 3283 Handle<String> replace,
3284 bool* found, 3284 bool* found,
3285 int recursion_limit) { 3285 int recursion_limit) {
3286 if (recursion_limit == 0) return Handle<String>::null(); 3286 if (recursion_limit == 0) return Handle<String>::null();
3287 if (subject->IsConsString()) { 3287 if (subject->IsConsString()) {
3288 ConsString* cons = ConsString::cast(*subject); 3288 ConsString* cons = ConsString::cast(*subject);
3289 Handle<String> first = Handle<String>(cons->first()); 3289 Handle<String> first = Handle<String>(cons->first());
3290 Handle<String> second = Handle<String>(cons->second()); 3290 Handle<String> second = Handle<String>(cons->second());
3291 Handle<String> new_first = 3291 Handle<String> new_first =
3292 StringReplaceOneCharWithString(isolate, 3292 StringReplaceOneCharWithString(isolate,
3293 first, 3293 first,
3294 search, 3294 search,
3295 replace, 3295 replace,
3296 found, 3296 found,
3297 recursion_limit - 1); 3297 recursion_limit - 1);
3298 if (*found) return isolate->factory()->NewConsString(new_first, second); 3298 if (*found) return isolate->factory()->NewConsString(new_first, second);
3299 if (new_first.is_null()) return new_first; 3299 if (new_first.is_null()) return new_first;
3300 3300
3301 Handle<String> new_second = 3301 Handle<String> new_second =
3302 StringReplaceOneCharWithString(isolate, 3302 StringReplaceOneCharWithString(isolate,
3303 second, 3303 second,
3304 search, 3304 search,
3305 replace, 3305 replace,
3306 found, 3306 found,
3307 recursion_limit - 1); 3307 recursion_limit - 1);
3308 if (*found) return isolate->factory()->NewConsString(first, new_second); 3308 if (*found) return isolate->factory()->NewConsString(first, new_second);
3309 if (new_second.is_null()) return new_second; 3309 if (new_second.is_null()) return new_second;
3310 3310
3311 return subject; 3311 return subject;
3312 } else { 3312 } else {
3313 int index = Runtime::StringMatch(isolate, subject, search, 0); 3313 int index = Runtime::StringMatch(isolate, subject, search, 0);
3314 if (index == -1) return subject; 3314 if (index == -1) return subject;
3315 *found = true; 3315 *found = true;
3316 Handle<String> first = isolate->factory()->NewSubString(subject, 0, index); 3316 Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
3317 Handle<String> cons1 = isolate->factory()->NewConsString(first, replace); 3317 Handle<String> cons1 = isolate->factory()->NewConsString(first, replace);
3318 Handle<String> second = 3318 Handle<String> second =
3319 isolate->factory()->NewSubString(subject, index + 1, subject->length()); 3319 isolate->factory()->NewSubString(subject, index + 1, subject->length());
3320 return isolate->factory()->NewConsString(cons1, second); 3320 return isolate->factory()->NewConsString(cons1, second);
3321 } 3321 }
3322 } 3322 }
3323 3323
3324 3324
3325 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) { 3325 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
3326 ASSERT(args.length() == 3); 3326 ASSERT(args.length() == 3);
3327 HandleScope scope(isolate); 3327 HandleScope scope(isolate);
3328 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); 3328 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3329 CONVERT_ARG_HANDLE_CHECKED(String, search, 1); 3329 CONVERT_ARG_HANDLE_CHECKED(String, search, 1);
3330 CONVERT_ARG_HANDLE_CHECKED(String, replace, 2); 3330 CONVERT_ARG_HANDLE_CHECKED(String, replace, 2);
3331 3331
3332 // If the cons string tree is too deep, we simply abort the recursion and 3332 // If the cons string tree is too deep, we simply abort the recursion and
3333 // retry with a flattened subject string. 3333 // retry with a flattened subject string.
3334 const int kRecursionLimit = 0x1000; 3334 const int kRecursionLimit = 0x1000;
3335 bool found = false; 3335 bool found = false;
3336 Handle<String> result = StringReplaceOneCharWithString(isolate, 3336 Handle<String> result = StringReplaceOneCharWithString(isolate,
3337 subject, 3337 subject,
3338 search, 3338 search,
3339 replace, 3339 replace,
3340 &found, 3340 &found,
3341 kRecursionLimit); 3341 kRecursionLimit);
3342 if (!result.is_null()) return *result; 3342 if (!result.is_null()) return *result;
3343 return *StringReplaceOneCharWithString(isolate, 3343 return *StringReplaceOneCharWithString(isolate,
3344 FlattenGetString(subject), 3344 FlattenGetString(subject),
3345 search, 3345 search,
3346 replace, 3346 replace,
3347 &found, 3347 &found,
3348 kRecursionLimit); 3348 kRecursionLimit);
3349 } 3349 }
3350 3350
3351 3351
3352 // Perform string match of pattern on subject, starting at start index. 3352 // Perform string match of pattern on subject, starting at start index.
3353 // Caller must ensure that 0 <= start_index <= sub->length(), 3353 // Caller must ensure that 0 <= start_index <= sub->length(),
3354 // and should check that pat->length() + start_index <= sub->length(). 3354 // and should check that pat->length() + start_index <= sub->length().
3355 int Runtime::StringMatch(Isolate* isolate, 3355 int Runtime::StringMatch(Isolate* isolate,
3356 Handle<String> sub, 3356 Handle<String> sub,
3357 Handle<String> pat, 3357 Handle<String> pat,
3358 int start_index) { 3358 int start_index) {
3359 ASSERT(0 <= start_index); 3359 ASSERT(0 <= start_index);
3360 ASSERT(start_index <= sub->length()); 3360 ASSERT(start_index <= sub->length());
3361 3361
3362 int pattern_length = pat->length(); 3362 int pattern_length = pat->length();
3363 if (pattern_length == 0) return start_index; 3363 if (pattern_length == 0) return start_index;
3364 3364
3365 int subject_length = sub->length(); 3365 int subject_length = sub->length();
3366 if (start_index + pattern_length > subject_length) return -1; 3366 if (start_index + pattern_length > subject_length) return -1;
3367 3367
3368 if (!sub->IsFlat()) FlattenString(sub); 3368 if (!sub->IsFlat()) FlattenString(sub);
3369 if (!pat->IsFlat()) FlattenString(pat); 3369 if (!pat->IsFlat()) FlattenString(pat);
3370 3370
3371 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 3371 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
3372 // Extract flattened substrings of cons strings before determining asciiness. 3372 // Extract flattened substrings of cons strings before determining asciiness.
3373 String::FlatContent seq_sub = sub->GetFlatContent(); 3373 String::FlatContent seq_sub = sub->GetFlatContent();
3374 String::FlatContent seq_pat = pat->GetFlatContent(); 3374 String::FlatContent seq_pat = pat->GetFlatContent();
3375 3375
3376 // dispatch on type of strings 3376 // dispatch on type of strings
3377 if (seq_pat.IsAscii()) { 3377 if (seq_pat.IsAscii()) {
3378 Vector<const char> pat_vector = seq_pat.ToAsciiVector(); 3378 Vector<const char> pat_vector = seq_pat.ToAsciiVector();
3379 if (seq_sub.IsAscii()) { 3379 if (seq_sub.IsAscii()) {
3380 return SearchString(isolate, 3380 return SearchString(isolate,
3381 seq_sub.ToAsciiVector(), 3381 seq_sub.ToAsciiVector(),
3382 pat_vector, 3382 pat_vector,
3383 start_index); 3383 start_index);
3384 } 3384 }
3385 return SearchString(isolate, 3385 return SearchString(isolate,
3386 seq_sub.ToUC16Vector(), 3386 seq_sub.ToUC16Vector(),
3387 pat_vector, 3387 pat_vector,
3388 start_index); 3388 start_index);
3389 } 3389 }
3390 Vector<const uc16> pat_vector = seq_pat.ToUC16Vector(); 3390 Vector<const uc16> pat_vector = seq_pat.ToUC16Vector();
3391 if (seq_sub.IsAscii()) { 3391 if (seq_sub.IsAscii()) {
3392 return SearchString(isolate, 3392 return SearchString(isolate,
3393 seq_sub.ToAsciiVector(), 3393 seq_sub.ToAsciiVector(),
3394 pat_vector, 3394 pat_vector,
3395 start_index); 3395 start_index);
3396 } 3396 }
3397 return SearchString(isolate, 3397 return SearchString(isolate,
3398 seq_sub.ToUC16Vector(), 3398 seq_sub.ToUC16Vector(),
3399 pat_vector, 3399 pat_vector,
3400 start_index); 3400 start_index);
3401 } 3401 }
3402 3402
3403 3403
3404 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) { 3404 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
3405 HandleScope scope(isolate); // create a new handle scope 3405 HandleScope scope(isolate); // create a new handle scope
3406 ASSERT(args.length() == 3); 3406 ASSERT(args.length() == 3);
3407 3407
3408 CONVERT_ARG_HANDLE_CHECKED(String, sub, 0); 3408 CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
3409 CONVERT_ARG_HANDLE_CHECKED(String, pat, 1); 3409 CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
3410 3410
3411 Object* index = args[2]; 3411 Object* index = args[2];
3412 uint32_t start_index; 3412 uint32_t start_index;
3413 if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1); 3413 if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3414 3414
3415 RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length())); 3415 RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
3416 int position = 3416 int position =
3417 Runtime::StringMatch(isolate, sub, pat, start_index); 3417 Runtime::StringMatch(isolate, sub, pat, start_index);
3418 return Smi::FromInt(position); 3418 return Smi::FromInt(position);
3419 } 3419 }
3420 3420
3421 3421
3422 template <typename schar, typename pchar> 3422 template <typename schar, typename pchar>
3423 static int StringMatchBackwards(Vector<const schar> subject, 3423 static int StringMatchBackwards(Vector<const schar> subject,
3424 Vector<const pchar> pattern, 3424 Vector<const pchar> pattern,
3425 int idx) { 3425 int idx) {
3426 int pattern_length = pattern.length(); 3426 int pattern_length = pattern.length();
3427 ASSERT(pattern_length >= 1); 3427 ASSERT(pattern_length >= 1);
3428 ASSERT(idx + pattern_length <= subject.length()); 3428 ASSERT(idx + pattern_length <= subject.length());
3429 3429
3430 if (sizeof(schar) == 1 && sizeof(pchar) > 1) { 3430 if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
3431 for (int i = 0; i < pattern_length; i++) { 3431 for (int i = 0; i < pattern_length; i++) {
3432 uc16 c = pattern[i]; 3432 uc16 c = pattern[i];
3433 if (c > String::kMaxAsciiCharCode) { 3433 if (c > String::kMaxAsciiCharCode) {
3434 return -1; 3434 return -1;
3435 } 3435 }
3436 } 3436 }
3437 } 3437 }
3438 3438
3439 pchar pattern_first_char = pattern[0]; 3439 pchar pattern_first_char = pattern[0];
3440 for (int i = idx; i >= 0; i--) { 3440 for (int i = idx; i >= 0; i--) {
3441 if (subject[i] != pattern_first_char) continue; 3441 if (subject[i] != pattern_first_char) continue;
3442 int j = 1; 3442 int j = 1;
3443 while (j < pattern_length) { 3443 while (j < pattern_length) {
3444 if (pattern[j] != subject[i+j]) { 3444 if (pattern[j] != subject[i+j]) {
3445 break; 3445 break;
3446 } 3446 }
3447 j++; 3447 j++;
3448 } 3448 }
3449 if (j == pattern_length) { 3449 if (j == pattern_length) {
3450 return i; 3450 return i;
3451 } 3451 }
3452 } 3452 }
3453 return -1; 3453 return -1;
3454 } 3454 }
3455 3455
3456 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) { 3456 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
3457 HandleScope scope(isolate); // create a new handle scope 3457 HandleScope scope(isolate); // create a new handle scope
3458 ASSERT(args.length() == 3); 3458 ASSERT(args.length() == 3);
3459 3459
3460 CONVERT_ARG_HANDLE_CHECKED(String, sub, 0); 3460 CONVERT_ARG_HANDLE_CHECKED(String, sub, 0);
3461 CONVERT_ARG_HANDLE_CHECKED(String, pat, 1); 3461 CONVERT_ARG_HANDLE_CHECKED(String, pat, 1);
3462 3462
3463 Object* index = args[2]; 3463 Object* index = args[2];
3464 uint32_t start_index; 3464 uint32_t start_index;
3465 if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1); 3465 if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
3466 3466
3467 uint32_t pat_length = pat->length(); 3467 uint32_t pat_length = pat->length();
3468 uint32_t sub_length = sub->length(); 3468 uint32_t sub_length = sub->length();
3469 3469
3470 if (start_index + pat_length > sub_length) { 3470 if (start_index + pat_length > sub_length) {
3471 start_index = sub_length - pat_length; 3471 start_index = sub_length - pat_length;
3472 } 3472 }
3473 3473
3474 if (pat_length == 0) { 3474 if (pat_length == 0) {
3475 return Smi::FromInt(start_index); 3475 return Smi::FromInt(start_index);
3476 } 3476 }
3477 3477
3478 if (!sub->IsFlat()) FlattenString(sub); 3478 if (!sub->IsFlat()) FlattenString(sub);
3479 if (!pat->IsFlat()) FlattenString(pat); 3479 if (!pat->IsFlat()) FlattenString(pat);
3480 3480
3481 int position = -1; 3481 int position = -1;
3482 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 3482 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
3483 3483
3484 String::FlatContent sub_content = sub->GetFlatContent(); 3484 String::FlatContent sub_content = sub->GetFlatContent();
3485 String::FlatContent pat_content = pat->GetFlatContent(); 3485 String::FlatContent pat_content = pat->GetFlatContent();
3486 3486
3487 if (pat_content.IsAscii()) { 3487 if (pat_content.IsAscii()) {
3488 Vector<const char> pat_vector = pat_content.ToAsciiVector(); 3488 Vector<const char> pat_vector = pat_content.ToAsciiVector();
3489 if (sub_content.IsAscii()) { 3489 if (sub_content.IsAscii()) {
3490 position = StringMatchBackwards(sub_content.ToAsciiVector(), 3490 position = StringMatchBackwards(sub_content.ToAsciiVector(),
3491 pat_vector, 3491 pat_vector,
3492 start_index); 3492 start_index);
3493 } else { 3493 } else {
3494 position = StringMatchBackwards(sub_content.ToUC16Vector(), 3494 position = StringMatchBackwards(sub_content.ToUC16Vector(),
3495 pat_vector, 3495 pat_vector,
3496 start_index); 3496 start_index);
3497 } 3497 }
3498 } else { 3498 } else {
3499 Vector<const uc16> pat_vector = pat_content.ToUC16Vector(); 3499 Vector<const uc16> pat_vector = pat_content.ToUC16Vector();
3500 if (sub_content.IsAscii()) { 3500 if (sub_content.IsAscii()) {
3501 position = StringMatchBackwards(sub_content.ToAsciiVector(), 3501 position = StringMatchBackwards(sub_content.ToAsciiVector(),
3502 pat_vector, 3502 pat_vector,
3503 start_index); 3503 start_index);
3504 } else { 3504 } else {
3505 position = StringMatchBackwards(sub_content.ToUC16Vector(), 3505 position = StringMatchBackwards(sub_content.ToUC16Vector(),
3506 pat_vector, 3506 pat_vector,
3507 start_index); 3507 start_index);
3508 } 3508 }
3509 } 3509 }
3510 3510
3511 return Smi::FromInt(position); 3511 return Smi::FromInt(position);
3512 } 3512 }
3513 3513
3514 3514
3515 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) { 3515 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
3516 NoHandleAllocation ha; 3516 NoHandleAllocation ha;
3517 ASSERT(args.length() == 2); 3517 ASSERT(args.length() == 2);
3518 3518
3519 CONVERT_ARG_CHECKED(String, str1, 0); 3519 CONVERT_ARG_CHECKED(String, str1, 0);
3520 CONVERT_ARG_CHECKED(String, str2, 1); 3520 CONVERT_ARG_CHECKED(String, str2, 1);
3521 3521
3522 if (str1 == str2) return Smi::FromInt(0); // Equal. 3522 if (str1 == str2) return Smi::FromInt(0); // Equal.
3523 int str1_length = str1->length(); 3523 int str1_length = str1->length();
3524 int str2_length = str2->length(); 3524 int str2_length = str2->length();
3525 3525
3526 // Decide trivial cases without flattening. 3526 // Decide trivial cases without flattening.
3527 if (str1_length == 0) { 3527 if (str1_length == 0) {
3528 if (str2_length == 0) return Smi::FromInt(0); // Equal. 3528 if (str2_length == 0) return Smi::FromInt(0); // Equal.
3529 return Smi::FromInt(-str2_length); 3529 return Smi::FromInt(-str2_length);
3530 } else { 3530 } else {
3531 if (str2_length == 0) return Smi::FromInt(str1_length); 3531 if (str2_length == 0) return Smi::FromInt(str1_length);
3532 } 3532 }
3533 3533
3534 int end = str1_length < str2_length ? str1_length : str2_length; 3534 int end = str1_length < str2_length ? str1_length : str2_length;
3535 3535
3536 // No need to flatten if we are going to find the answer on the first 3536 // No need to flatten if we are going to find the answer on the first
3537 // character. At this point we know there is at least one character 3537 // character. At this point we know there is at least one character
3538 // in each string, due to the trivial case handling above. 3538 // in each string, due to the trivial case handling above.
3539 int d = str1->Get(0) - str2->Get(0); 3539 int d = str1->Get(0) - str2->Get(0);
3540 if (d != 0) return Smi::FromInt(d); 3540 if (d != 0) return Smi::FromInt(d);
3541 3541
3542 str1->TryFlatten(); 3542 str1->TryFlatten();
3543 str2->TryFlatten(); 3543 str2->TryFlatten();
3544 3544
3545 StringInputBuffer& buf1 = 3545 StringInputBuffer& buf1 =
3546 *isolate->runtime_state()->string_locale_compare_buf1(); 3546 *isolate->runtime_state()->string_locale_compare_buf1();
3547 StringInputBuffer& buf2 = 3547 StringInputBuffer& buf2 =
3548 *isolate->runtime_state()->string_locale_compare_buf2(); 3548 *isolate->runtime_state()->string_locale_compare_buf2();
3549 3549
3550 buf1.Reset(str1); 3550 buf1.Reset(str1);
3551 buf2.Reset(str2); 3551 buf2.Reset(str2);
3552 3552
3553 for (int i = 0; i < end; i++) { 3553 for (int i = 0; i < end; i++) {
3554 uint16_t char1 = buf1.GetNext(); 3554 uint16_t char1 = buf1.GetNext();
3555 uint16_t char2 = buf2.GetNext(); 3555 uint16_t char2 = buf2.GetNext();
3556 if (char1 != char2) return Smi::FromInt(char1 - char2); 3556 if (char1 != char2) return Smi::FromInt(char1 - char2);
3557 } 3557 }
3558 3558
3559 return Smi::FromInt(str1_length - str2_length); 3559 return Smi::FromInt(str1_length - str2_length);
3560 } 3560 }
3561 3561
3562 3562
3563 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) { 3563 RUNTIME_FUNCTION(MaybeObject*, Runtime_SubString) {
3564 NoHandleAllocation ha; 3564 NoHandleAllocation ha;
3565 ASSERT(args.length() == 3); 3565 ASSERT(args.length() == 3);
3566 3566
3567 CONVERT_ARG_CHECKED(String, value, 0); 3567 CONVERT_ARG_CHECKED(String, value, 0);
3568 int start, end; 3568 int start, end;
3569 // We have a fast integer-only case here to avoid a conversion to double in 3569 // We have a fast integer-only case here to avoid a conversion to double in
3570 // the common case where from and to are Smis. 3570 // the common case where from and to are Smis.
3571 if (args[1]->IsSmi() && args[2]->IsSmi()) { 3571 if (args[1]->IsSmi() && args[2]->IsSmi()) {
3572 CONVERT_SMI_ARG_CHECKED(from_number, 1); 3572 CONVERT_SMI_ARG_CHECKED(from_number, 1);
3573 CONVERT_SMI_ARG_CHECKED(to_number, 2); 3573 CONVERT_SMI_ARG_CHECKED(to_number, 2);
3574 start = from_number; 3574 start = from_number;
3575 end = to_number; 3575 end = to_number;
3576 } else { 3576 } else {
3577 CONVERT_DOUBLE_ARG_CHECKED(from_number, 1); 3577 CONVERT_DOUBLE_ARG_CHECKED(from_number, 1);
3578 CONVERT_DOUBLE_ARG_CHECKED(to_number, 2); 3578 CONVERT_DOUBLE_ARG_CHECKED(to_number, 2);
3579 start = FastD2IChecked(from_number); 3579 start = FastD2IChecked(from_number);
3580 end = FastD2IChecked(to_number); 3580 end = FastD2IChecked(to_number);
3581 } 3581 }
3582 RUNTIME_ASSERT(end >= start); 3582 RUNTIME_ASSERT(end >= start);
3583 RUNTIME_ASSERT(start >= 0); 3583 RUNTIME_ASSERT(start >= 0);
3584 RUNTIME_ASSERT(end <= value->length()); 3584 RUNTIME_ASSERT(end <= value->length());
3585 isolate->counters()->sub_string_runtime()->Increment(); 3585 isolate->counters()->sub_string_runtime()->Increment();
3586 return value->SubString(start, end); 3586 return value->SubString(start, end);
3587 } 3587 }
3588 3588
3589 3589
3590 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) { 3590 RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) {
3591 ASSERT_EQ(3, args.length()); 3591 ASSERT_EQ(3, args.length());
3592 3592
3593 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); 3593 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
3594 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); 3594 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
3595 CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2); 3595 CONVERT_ARG_HANDLE_CHECKED(JSArray, regexp_info, 2);
3596 HandleScope handles; 3596 HandleScope handles;
3597 3597
3598 RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate); 3598 RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3599 if (global_cache.HasException()) return Failure::Exception(); 3599 if (global_cache.HasException()) return Failure::Exception();
3600 3600
3601 int capture_count = regexp->CaptureCount(); 3601 int capture_count = regexp->CaptureCount();
3602 3602
3603 Zone* zone = isolate->runtime_zone(); 3603 Zone* zone = isolate->runtime_zone();
3604 ZoneScope zone_space(zone, DELETE_ON_EXIT); 3604 ZoneScope zone_space(zone, DELETE_ON_EXIT);
3605 ZoneList<int> offsets(8, zone); 3605 ZoneList<int> offsets(8, zone);
3606 3606
3607 while (true) { 3607 while (true) {
3608 int32_t* match = global_cache.FetchNext(); 3608 int32_t* match = global_cache.FetchNext();
3609 if (match == NULL) break; 3609 if (match == NULL) break;
3610 offsets.Add(match[0], zone); // start 3610 offsets.Add(match[0], zone); // start
3611 offsets.Add(match[1], zone); // end 3611 offsets.Add(match[1], zone); // end
3612 } 3612 }
3613 3613
3614 if (global_cache.HasException()) return Failure::Exception(); 3614 if (global_cache.HasException()) return Failure::Exception();
3615 3615
3616 if (offsets.length() == 0) { 3616 if (offsets.length() == 0) {
3617 // Not a single match. 3617 // Not a single match.
3618 return isolate->heap()->null_value(); 3618 return isolate->heap()->null_value();
3619 } 3619 }
3620 3620
3621 RegExpImpl::SetLastMatchInfo(regexp_info, 3621 RegExpImpl::SetLastMatchInfo(regexp_info,
3622 subject, 3622 subject,
3623 capture_count, 3623 capture_count,
3624 global_cache.LastSuccessfulMatch()); 3624 global_cache.LastSuccessfulMatch());
3625 3625
3626 int matches = offsets.length() / 2; 3626 int matches = offsets.length() / 2;
3627 Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches); 3627 Handle<FixedArray> elements = isolate->factory()->NewFixedArray(matches);
3628 Handle<String> substring = 3628 Handle<String> substring =
3629 isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1)); 3629 isolate->factory()->NewSubString(subject, offsets.at(0), offsets.at(1));
3630 elements->set(0, *substring); 3630 elements->set(0, *substring);
3631 for (int i = 1; i < matches; i++) { 3631 for (int i = 1; i < matches; i++) {
3632 HandleScope temp_scope(isolate); 3632 HandleScope temp_scope(isolate);
3633 int from = offsets.at(i * 2); 3633 int from = offsets.at(i * 2);
3634 int to = offsets.at(i * 2 + 1); 3634 int to = offsets.at(i * 2 + 1);
3635 Handle<String> substring = 3635 Handle<String> substring =
3636 isolate->factory()->NewProperSubString(subject, from, to); 3636 isolate->factory()->NewProperSubString(subject, from, to);
3637 elements->set(i, *substring); 3637 elements->set(i, *substring);
3638 } 3638 }
3639 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements); 3639 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(elements);
3640 result->set_length(Smi::FromInt(matches)); 3640 result->set_length(Smi::FromInt(matches));
3641 return *result; 3641 return *result;
3642 } 3642 }
3643 3643
3644 3644
3645 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain 3645 // Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
3646 // separate last match info. See comment on that function. 3646 // separate last match info. See comment on that function.
3647 template<bool has_capture> 3647 template<bool has_capture>
3648 static MaybeObject* SearchRegExpMultiple( 3648 static MaybeObject* SearchRegExpMultiple(
3649 Isolate* isolate, 3649 Isolate* isolate,
3650 Handle<String> subject, 3650 Handle<String> subject,
3651 Handle<JSRegExp> regexp, 3651 Handle<JSRegExp> regexp,
3652 Handle<JSArray> last_match_array, 3652 Handle<JSArray> last_match_array,
3653 Handle<JSArray> result_array) { 3653 Handle<JSArray> result_array) {
3654 ASSERT(subject->IsFlat()); 3654 ASSERT(subject->IsFlat());
3655 ASSERT_NE(has_capture, regexp->CaptureCount() == 0); 3655 ASSERT_NE(has_capture, regexp->CaptureCount() == 0);
3656 3656
3657 int capture_count = regexp->CaptureCount(); 3657 int capture_count = regexp->CaptureCount();
3658 int subject_length = subject->length(); 3658 int subject_length = subject->length();
3659 3659
3660 static const int kMinLengthToCache = 0x1000; 3660 static const int kMinLengthToCache = 0x1000;
3661 3661
3662 if (subject_length > kMinLengthToCache) { 3662 if (subject_length > kMinLengthToCache) {
3663 Handle<Object> cached_answer(RegExpResultsCache::Lookup( 3663 Handle<Object> cached_answer(RegExpResultsCache::Lookup(
3664 isolate->heap(), 3664 isolate->heap(),
3665 *subject, 3665 *subject,
3666 regexp->data(), 3666 regexp->data(),
3667 RegExpResultsCache::REGEXP_MULTIPLE_INDICES)); 3667 RegExpResultsCache::REGEXP_MULTIPLE_INDICES));
3668 if (*cached_answer != Smi::FromInt(0)) { 3668 if (*cached_answer != Smi::FromInt(0)) {
3669 Handle<FixedArray> cached_fixed_array = 3669 Handle<FixedArray> cached_fixed_array =
3670 Handle<FixedArray>(FixedArray::cast(*cached_answer)); 3670 Handle<FixedArray>(FixedArray::cast(*cached_answer));
3671 // The cache FixedArray is a COW-array and can therefore be reused. 3671 // The cache FixedArray is a COW-array and can therefore be reused.
3672 isolate->factory()->SetContent(result_array, cached_fixed_array); 3672 isolate->factory()->SetContent(result_array, cached_fixed_array);
3673 // The actual length of the result array is stored in the last element of 3673 // The actual length of the result array is stored in the last element of
3674 // the backing store (the backing FixedArray may have a larger capacity). 3674 // the backing store (the backing FixedArray may have a larger capacity).
3675 Object* cached_fixed_array_last_element = 3675 Object* cached_fixed_array_last_element =
3676 cached_fixed_array->get(cached_fixed_array->length() - 1); 3676 cached_fixed_array->get(cached_fixed_array->length() - 1);
3677 Smi* js_array_length = Smi::cast(cached_fixed_array_last_element); 3677 Smi* js_array_length = Smi::cast(cached_fixed_array_last_element);
3678 result_array->set_length(js_array_length); 3678 result_array->set_length(js_array_length);
3679 RegExpImpl::SetLastMatchInfo( 3679 RegExpImpl::SetLastMatchInfo(
3680 last_match_array, subject, capture_count, NULL); 3680 last_match_array, subject, capture_count, NULL);
3681 return *result_array; 3681 return *result_array;
3682 } 3682 }
3683 } 3683 }
3684 3684
3685 RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate); 3685 RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate);
3686 if (global_cache.HasException()) return Failure::Exception(); 3686 if (global_cache.HasException()) return Failure::Exception();
3687 3687
3688 Handle<FixedArray> result_elements; 3688 Handle<FixedArray> result_elements;
3689 if (result_array->HasFastObjectElements()) { 3689 if (result_array->HasFastObjectElements()) {
3690 result_elements = 3690 result_elements =
3691 Handle<FixedArray>(FixedArray::cast(result_array->elements())); 3691 Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3692 } 3692 }
3693 if (result_elements.is_null() || result_elements->length() < 16) { 3693 if (result_elements.is_null() || result_elements->length() < 16) {
3694 result_elements = isolate->factory()->NewFixedArrayWithHoles(16); 3694 result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
3695 } 3695 }
3696 3696
3697 FixedArrayBuilder builder(result_elements); 3697 FixedArrayBuilder builder(result_elements);
3698 3698
3699 // Position to search from. 3699 // Position to search from.
3700 int match_start = -1; 3700 int match_start = -1;
3701 int match_end = 0; 3701 int match_end = 0;
3702 bool first = true; 3702 bool first = true;
3703 3703
3704 // Two smis before and after the match, for very long strings. 3704 // Two smis before and after the match, for very long strings.
3705 static const int kMaxBuilderEntriesPerRegExpMatch = 5; 3705 static const int kMaxBuilderEntriesPerRegExpMatch = 5;
3706 3706
3707 while (true) { 3707 while (true) {
3708 int32_t* current_match = global_cache.FetchNext(); 3708 int32_t* current_match = global_cache.FetchNext();
3709 if (current_match == NULL) break; 3709 if (current_match == NULL) break;
3710 match_start = current_match[0]; 3710 match_start = current_match[0];
3711 builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); 3711 builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3712 if (match_end < match_start) { 3712 if (match_end < match_start) {
3713 ReplacementStringBuilder::AddSubjectSlice(&builder, 3713 ReplacementStringBuilder::AddSubjectSlice(&builder,
3714 match_end, 3714 match_end,
3715 match_start); 3715 match_start);
3716 } 3716 }
3717 match_end = current_match[1]; 3717 match_end = current_match[1];
3718 { 3718 {
3719 // Avoid accumulating new handles inside loop. 3719 // Avoid accumulating new handles inside loop.
3720 HandleScope temp_scope(isolate); 3720 HandleScope temp_scope(isolate);
3721 Handle<String> match; 3721 Handle<String> match;
3722 if (!first) { 3722 if (!first) {
3723 match = isolate->factory()->NewProperSubString(subject, 3723 match = isolate->factory()->NewProperSubString(subject,
3724 match_start, 3724 match_start,
3725 match_end); 3725 match_end);
3726 } else { 3726 } else {
3727 match = isolate->factory()->NewSubString(subject, 3727 match = isolate->factory()->NewSubString(subject,
3728 match_start, 3728 match_start,
3729 match_end); 3729 match_end);
3730 first = false; 3730 first = false;
3731 } 3731 }
3732 3732
3733 if (has_capture) { 3733 if (has_capture) {
3734 // Arguments array to replace function is match, captures, index and 3734 // Arguments array to replace function is match, captures, index and
3735 // subject, i.e., 3 + capture count in total. 3735 // subject, i.e., 3 + capture count in total.
3736 Handle<FixedArray> elements = 3736 Handle<FixedArray> elements =
3737 isolate->factory()->NewFixedArray(3 + capture_count); 3737 isolate->factory()->NewFixedArray(3 + capture_count);
3738 3738
3739 elements->set(0, *match); 3739 elements->set(0, *match);
3740 for (int i = 1; i <= capture_count; i++) { 3740 for (int i = 1; i <= capture_count; i++) {
3741 int start = current_match[i * 2]; 3741 int start = current_match[i * 2];
3742 if (start >= 0) { 3742 if (start >= 0) {
3743 int end = current_match[i * 2 + 1]; 3743 int end = current_match[i * 2 + 1];
3744 ASSERT(start <= end); 3744 ASSERT(start <= end);
3745 Handle<String> substring = 3745 Handle<String> substring =
3746 isolate->factory()->NewSubString(subject, start, end); 3746 isolate->factory()->NewSubString(subject, start, end);
3747 elements->set(i, *substring); 3747 elements->set(i, *substring);
3748 } else { 3748 } else {
3749 ASSERT(current_match[i * 2 + 1] < 0); 3749 ASSERT(current_match[i * 2 + 1] < 0);
3750 elements->set(i, isolate->heap()->undefined_value()); 3750 elements->set(i, isolate->heap()->undefined_value());
3751 } 3751 }
3752 } 3752 }
3753 elements->set(capture_count + 1, Smi::FromInt(match_start)); 3753 elements->set(capture_count + 1, Smi::FromInt(match_start));
3754 elements->set(capture_count + 2, *subject); 3754 elements->set(capture_count + 2, *subject);
3755 builder.Add(*isolate->factory()->NewJSArrayWithElements(elements)); 3755 builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
3756 } else { 3756 } else {
3757 builder.Add(*match); 3757 builder.Add(*match);
3758 } 3758 }
3759 } 3759 }
3760 } 3760 }
3761 3761
3762 if (global_cache.HasException()) return Failure::Exception(); 3762 if (global_cache.HasException()) return Failure::Exception();
3763 3763
3764 if (match_start >= 0) { 3764 if (match_start >= 0) {
3765 // Finished matching, with at least one match. 3765 // Finished matching, with at least one match.
3766 if (match_end < subject_length) { 3766 if (match_end < subject_length) {
3767 ReplacementStringBuilder::AddSubjectSlice(&builder, 3767 ReplacementStringBuilder::AddSubjectSlice(&builder,
3768 match_end, 3768 match_end,
3769 subject_length); 3769 subject_length);
3770 } 3770 }
3771 3771
3772 RegExpImpl::SetLastMatchInfo( 3772 RegExpImpl::SetLastMatchInfo(
3773 last_match_array, subject, capture_count, NULL); 3773 last_match_array, subject, capture_count, NULL);
3774 3774
3775 if (subject_length > kMinLengthToCache) { 3775 if (subject_length > kMinLengthToCache) {
3776 // Store the length of the result array into the last element of the 3776 // Store the length of the result array into the last element of the
3777 // backing FixedArray. 3777 // backing FixedArray.
3778 builder.EnsureCapacity(1); 3778 builder.EnsureCapacity(1);
3779 Handle<FixedArray> fixed_array = builder.array(); 3779 Handle<FixedArray> fixed_array = builder.array();
3780 fixed_array->set(fixed_array->length() - 1, 3780 fixed_array->set(fixed_array->length() - 1,
3781 Smi::FromInt(builder.length())); 3781 Smi::FromInt(builder.length()));
3782 // Cache the result and turn the FixedArray into a COW array. 3782 // Cache the result and turn the FixedArray into a COW array.
3783 RegExpResultsCache::Enter(isolate->heap(), 3783 RegExpResultsCache::Enter(isolate->heap(),
3784 *subject, 3784 *subject,
3785 regexp->data(), 3785 regexp->data(),
3786 *fixed_array, 3786 *fixed_array,
3787 RegExpResultsCache::REGEXP_MULTIPLE_INDICES); 3787 RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
3788 } 3788 }
3789 return *builder.ToJSArray(result_array); 3789 return *builder.ToJSArray(result_array);
3790 } else { 3790 } else {
3791 return isolate->heap()->null_value(); // No matches at all. 3791 return isolate->heap()->null_value(); // No matches at all.
3792 } 3792 }
3793 } 3793 }
3794 3794
3795 3795
3796 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets 3796 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets
3797 // lastMatchInfoOverride to maintain the last match info, so we don't need to 3797 // lastMatchInfoOverride to maintain the last match info, so we don't need to
3798 // set any other last match array info. 3798 // set any other last match array info.
3799 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { 3799 RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) {
3800 ASSERT(args.length() == 4); 3800 ASSERT(args.length() == 4);
3801 HandleScope handles(isolate); 3801 HandleScope handles(isolate);
3802 3802
3803 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); 3803 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
3804 if (!subject->IsFlat()) FlattenString(subject); 3804 if (!subject->IsFlat()) FlattenString(subject);
3805 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); 3805 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
3806 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2); 3806 CONVERT_ARG_HANDLE_CHECKED(JSArray, last_match_info, 2);
3807 CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3); 3807 CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
3808 3808
3809 ASSERT(last_match_info->HasFastObjectElements()); 3809 ASSERT(last_match_info->HasFastObjectElements());
3810 ASSERT(regexp->GetFlags().is_global()); 3810 ASSERT(regexp->GetFlags().is_global());
3811 3811
3812 if (regexp->CaptureCount() == 0) { 3812 if (regexp->CaptureCount() == 0) {
3813 return SearchRegExpMultiple<false>( 3813 return SearchRegExpMultiple<false>(
3814 isolate, subject, regexp, last_match_info, result_array); 3814 isolate, subject, regexp, last_match_info, result_array);
3815 } else { 3815 } else {
3816 return SearchRegExpMultiple<true>( 3816 return SearchRegExpMultiple<true>(
3817 isolate, subject, regexp, last_match_info, result_array); 3817 isolate, subject, regexp, last_match_info, result_array);
3818 } 3818 }
3819 } 3819 }
3820 3820
3821 3821
3822 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) { 3822 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToRadixString) {
3823 NoHandleAllocation ha; 3823 NoHandleAllocation ha;
3824 ASSERT(args.length() == 2); 3824 ASSERT(args.length() == 2);
3825 CONVERT_SMI_ARG_CHECKED(radix, 1); 3825 CONVERT_SMI_ARG_CHECKED(radix, 1);
3826 RUNTIME_ASSERT(2 <= radix && radix <= 36); 3826 RUNTIME_ASSERT(2 <= radix && radix <= 36);
3827 3827
3828 // Fast case where the result is a one character string. 3828 // Fast case where the result is a one character string.
3829 if (args[0]->IsSmi()) { 3829 if (args[0]->IsSmi()) {
3830 int value = args.smi_at(0); 3830 int value = args.smi_at(0);
3831 if (value >= 0 && value < radix) { 3831 if (value >= 0 && value < radix) {
3832 // Character array used for conversion. 3832 // Character array used for conversion.
3833 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz"; 3833 static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
3834 return isolate->heap()-> 3834 return isolate->heap()->
3835 LookupSingleCharacterStringFromCode(kCharTable[value]); 3835 LookupSingleCharacterStringFromCode(kCharTable[value]);
3836 } 3836 }
3837 } 3837 }
3838 3838
3839 // Slow case. 3839 // Slow case.
3840 CONVERT_DOUBLE_ARG_CHECKED(value, 0); 3840 CONVERT_DOUBLE_ARG_CHECKED(value, 0);
3841 if (isnan(value)) { 3841 if (isnan(value)) {
3842 return *isolate->factory()->nan_symbol(); 3842 return *isolate->factory()->nan_symbol();
3843 } 3843 }
3844 if (isinf(value)) { 3844 if (isinf(value)) {
3845 if (value < 0) { 3845 if (value < 0) {
3846 return *isolate->factory()->minus_infinity_symbol(); 3846 return *isolate->factory()->minus_infinity_symbol();
3847 } 3847 }
3848 return *isolate->factory()->infinity_symbol(); 3848 return *isolate->factory()->infinity_symbol();
3849 } 3849 }
3850 char* str = DoubleToRadixCString(value, radix); 3850 char* str = DoubleToRadixCString(value, radix);
3851 MaybeObject* result = 3851 MaybeObject* result =
3852 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); 3852 isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3853 DeleteArray(str); 3853 DeleteArray(str);
3854 return result; 3854 return result;
3855 } 3855 }
3856 3856
3857 3857
3858 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) { 3858 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToFixed) {
3859 NoHandleAllocation ha; 3859 NoHandleAllocation ha;
3860 ASSERT(args.length() == 2); 3860 ASSERT(args.length() == 2);
3861 3861
3862 CONVERT_DOUBLE_ARG_CHECKED(value, 0); 3862 CONVERT_DOUBLE_ARG_CHECKED(value, 0);
3863 if (isnan(value)) { 3863 if (isnan(value)) {
3864 return *isolate->factory()->nan_symbol(); 3864 return *isolate->factory()->nan_symbol();
3865 } 3865 }
3866 if (isinf(value)) { 3866 if (isinf(value)) {
3867 if (value < 0) { 3867 if (value < 0) {
3868 return *isolate->factory()->minus_infinity_symbol(); 3868 return *isolate->factory()->minus_infinity_symbol();
3869 } 3869 }
3870 return *isolate->factory()->infinity_symbol(); 3870 return *isolate->factory()->infinity_symbol();
3871 } 3871 }
3872 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); 3872 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
3873 int f = FastD2IChecked(f_number); 3873 int f = FastD2IChecked(f_number);
3874 RUNTIME_ASSERT(f >= 0); 3874 RUNTIME_ASSERT(f >= 0);
3875 char* str = DoubleToFixedCString(value, f); 3875 char* str = DoubleToFixedCString(value, f);
3876 MaybeObject* res = 3876 MaybeObject* res =
3877 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); 3877 isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3878 DeleteArray(str); 3878 DeleteArray(str);
3879 return res; 3879 return res;
3880 } 3880 }
3881 3881
3882 3882
3883 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) { 3883 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToExponential) {
3884 NoHandleAllocation ha; 3884 NoHandleAllocation ha;
3885 ASSERT(args.length() == 2); 3885 ASSERT(args.length() == 2);
3886 3886
3887 CONVERT_DOUBLE_ARG_CHECKED(value, 0); 3887 CONVERT_DOUBLE_ARG_CHECKED(value, 0);
3888 if (isnan(value)) { 3888 if (isnan(value)) {
3889 return *isolate->factory()->nan_symbol(); 3889 return *isolate->factory()->nan_symbol();
3890 } 3890 }
3891 if (isinf(value)) { 3891 if (isinf(value)) {
3892 if (value < 0) { 3892 if (value < 0) {
3893 return *isolate->factory()->minus_infinity_symbol(); 3893 return *isolate->factory()->minus_infinity_symbol();
3894 } 3894 }
3895 return *isolate->factory()->infinity_symbol(); 3895 return *isolate->factory()->infinity_symbol();
3896 } 3896 }
3897 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); 3897 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
3898 int f = FastD2IChecked(f_number); 3898 int f = FastD2IChecked(f_number);
3899 RUNTIME_ASSERT(f >= -1 && f <= 20); 3899 RUNTIME_ASSERT(f >= -1 && f <= 20);
3900 char* str = DoubleToExponentialCString(value, f); 3900 char* str = DoubleToExponentialCString(value, f);
3901 MaybeObject* res = 3901 MaybeObject* res =
3902 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); 3902 isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3903 DeleteArray(str); 3903 DeleteArray(str);
3904 return res; 3904 return res;
3905 } 3905 }
3906 3906
3907 3907
3908 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) { 3908 RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberToPrecision) {
3909 NoHandleAllocation ha; 3909 NoHandleAllocation ha;
3910 ASSERT(args.length() == 2); 3910 ASSERT(args.length() == 2);
3911 3911
3912 CONVERT_DOUBLE_ARG_CHECKED(value, 0); 3912 CONVERT_DOUBLE_ARG_CHECKED(value, 0);
3913 if (isnan(value)) { 3913 if (isnan(value)) {
3914 return *isolate->factory()->nan_symbol(); 3914 return *isolate->factory()->nan_symbol();
3915 } 3915 }
3916 if (isinf(value)) { 3916 if (isinf(value)) {
3917 if (value < 0) { 3917 if (value < 0) {
3918 return *isolate->factory()->minus_infinity_symbol(); 3918 return *isolate->factory()->minus_infinity_symbol();
3919 } 3919 }
3920 return *isolate->factory()->infinity_symbol(); 3920 return *isolate->factory()->infinity_symbol();
3921 } 3921 }
3922 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1); 3922 CONVERT_DOUBLE_ARG_CHECKED(f_number, 1);
3923 int f = FastD2IChecked(f_number); 3923 int f = FastD2IChecked(f_number);
3924 RUNTIME_ASSERT(f >= 1 && f <= 21); 3924 RUNTIME_ASSERT(f >= 1 && f <= 21);
3925 char* str = DoubleToPrecisionCString(value, f); 3925 char* str = DoubleToPrecisionCString(value, f);
3926 MaybeObject* res = 3926 MaybeObject* res =
3927 isolate->heap()->AllocateStringFromAscii(CStrVector(str)); 3927 isolate->heap()->AllocateStringFromAscii(CStrVector(str));
3928 DeleteArray(str); 3928 DeleteArray(str);
3929 return res; 3929 return res;
3930 } 3930 }
3931 3931
3932 3932
3933 // Returns a single character string where first character equals 3933 // Returns a single character string where first character equals
3934 // string->Get(index). 3934 // string->Get(index).
3935 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { 3935 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
3936 if (index < static_cast<uint32_t>(string->length())) { 3936 if (index < static_cast<uint32_t>(string->length())) {
3937 string->TryFlatten(); 3937 string->TryFlatten();
3938 return LookupSingleCharacterStringFromCode( 3938 return LookupSingleCharacterStringFromCode(
3939 string->Get(index)); 3939 string->Get(index));
3940 } 3940 }
3941 return Execution::CharAt(string, index); 3941 return Execution::CharAt(string, index);
3942 } 3942 }
3943 3943
3944 3944
3945 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate, 3945 MaybeObject* Runtime::GetElementOrCharAt(Isolate* isolate,
3946 Handle<Object> object, 3946 Handle<Object> object,
3947 uint32_t index) { 3947 uint32_t index) {
3948 // Handle [] indexing on Strings 3948 // Handle [] indexing on Strings
3949 if (object->IsString()) { 3949 if (object->IsString()) {
3950 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); 3950 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
3951 if (!result->IsUndefined()) return *result; 3951 if (!result->IsUndefined()) return *result;
3952 } 3952 }
3953 3953
3954 // Handle [] indexing on String objects 3954 // Handle [] indexing on String objects
3955 if (object->IsStringObjectWithCharacterAt(index)) { 3955 if (object->IsStringObjectWithCharacterAt(index)) {
3956 Handle<JSValue> js_value = Handle<JSValue>::cast(object); 3956 Handle<JSValue> js_value = Handle<JSValue>::cast(object);
3957 Handle<Object> result = 3957 Handle<Object> result =
3958 GetCharAt(Handle<String>(String::cast(js_value->value())), index); 3958 GetCharAt(Handle<String>(String::cast(js_value->value())), index);
3959 if (!result->IsUndefined()) return *result; 3959 if (!result->IsUndefined()) return *result;
3960 } 3960 }
3961 3961
3962 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { 3962 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
3963 return object->GetPrototype()->GetElement(index); 3963 return object->GetPrototype()->GetElement(index);
3964 } 3964 }
3965 3965
3966 return object->GetElement(index); 3966 return object->GetElement(index);
3967 } 3967 }
3968 3968
3969 3969
3970 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate, 3970 MaybeObject* Runtime::GetObjectProperty(Isolate* isolate,
3971 Handle<Object> object, 3971 Handle<Object> object,
3972 Handle<Object> key) { 3972 Handle<Object> key) {
3973 HandleScope scope(isolate); 3973 HandleScope scope(isolate);
3974 3974
3975 if (object->IsUndefined() || object->IsNull()) { 3975 if (object->IsUndefined() || object->IsNull()) {
3976 Handle<Object> args[2] = { key, object }; 3976 Handle<Object> args[2] = { key, object };
3977 Handle<Object> error = 3977 Handle<Object> error =
3978 isolate->factory()->NewTypeError("non_object_property_load", 3978 isolate->factory()->NewTypeError("non_object_property_load",
3979 HandleVector(args, 2)); 3979 HandleVector(args, 2));
3980 return isolate->Throw(*error); 3980 return isolate->Throw(*error);
3981 } 3981 }
3982 3982
3983 // Check if the given key is an array index. 3983 // Check if the given key is an array index.
3984 uint32_t index; 3984 uint32_t index;
3985 if (key->ToArrayIndex(&index)) { 3985 if (key->ToArrayIndex(&index)) {
3986 return GetElementOrCharAt(isolate, object, index); 3986 return GetElementOrCharAt(isolate, object, index);
3987 } 3987 }
3988 3988
3989 // Convert the key to a string - possibly by calling back into JavaScript. 3989 // Convert the key to a string - possibly by calling back into JavaScript.
3990 Handle<String> name; 3990 Handle<String> name;
3991 if (key->IsString()) { 3991 if (key->IsString()) {
3992 name = Handle<String>::cast(key); 3992 name = Handle<String>::cast(key);
3993 } else { 3993 } else {
3994 bool has_pending_exception = false; 3994 bool has_pending_exception = false;
3995 Handle<Object> converted = 3995 Handle<Object> converted =
3996 Execution::ToString(key, &has_pending_exception); 3996 Execution::ToString(key, &has_pending_exception);
3997 if (has_pending_exception) return Failure::Exception(); 3997 if (has_pending_exception) return Failure::Exception();
3998 name = Handle<String>::cast(converted); 3998 name = Handle<String>::cast(converted);
3999 } 3999 }
4000 4000
4001 // Check if the name is trivially convertible to an index and get 4001 // Check if the name is trivially convertible to an index and get
4002 // the element if so. 4002 // the element if so.
4003 if (name->AsArrayIndex(&index)) { 4003 if (name->AsArrayIndex(&index)) {
4004 return GetElementOrCharAt(isolate, object, index); 4004 return GetElementOrCharAt(isolate, object, index);
4005 } else { 4005 } else {
4006 return object->GetProperty(*name); 4006 return object->GetProperty(*name);
4007 } 4007 }
4008 } 4008 }
4009 4009
4010 4010
4011 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) { 4011 RUNTIME_FUNCTION(MaybeObject*, Runtime_GetProperty) {
4012 NoHandleAllocation ha; 4012 NoHandleAllocation ha;
4013 ASSERT(args.length() == 2); 4013 ASSERT(args.length() == 2);
4014 4014
4015 Handle<Object> object = args.at<Object>(0); 4015 Handle<Object> object = args.at<Object>(0);
4016 Handle<Object> key = args.at<Object>(1); 4016 Handle<Object> key = args.at<Object>(1);
4017 4017
4018 return Runtime::GetObjectProperty(isolate, object, key); 4018 return Runtime::GetObjectProperty(isolate, object, key);
4019 } 4019 }
4020 4020
4021 4021
4022 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric. 4022 // KeyedStringGetProperty is called from KeyedLoadIC::GenerateGeneric.
4023 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) { 4023 RUNTIME_FUNCTION(MaybeObject*, Runtime_KeyedGetProperty) {
4024 NoHandleAllocation ha; 4024 NoHandleAllocation ha;
4025 ASSERT(args.length() == 2); 4025 ASSERT(args.length() == 2);
4026 4026
4027 // Fast cases for getting named properties of the receiver JSObject 4027 // Fast cases for getting named properties of the receiver JSObject
4028 // itself. 4028 // itself.
4029 // 4029 //
4030 // The global proxy objects has to be excluded since LocalLookup on 4030 // The global proxy objects has to be excluded since LocalLookup on
4031 // the global proxy object can return a valid result even though the 4031 // the global proxy object can return a valid result even though the
4032 // global proxy object never has properties. This is the case 4032 // global proxy object never has properties. This is the case
4033 // because the global proxy object forwards everything to its hidden 4033 // because the global proxy object forwards everything to its hidden
4034 // prototype including local lookups. 4034 // prototype including local lookups.
4035 // 4035 //
4036 // Additionally, we need to make sure that we do not cache results 4036 // Additionally, we need to make sure that we do not cache results
4037 // for objects that require access checks. 4037 // for objects that require access checks.
4038 if (args[0]->IsJSObject()) { 4038 if (args[0]->IsJSObject()) {
4039 if (!args[0]->IsJSGlobalProxy() && 4039 if (!args[0]->IsJSGlobalProxy() &&
4040 !args[0]->IsAccessCheckNeeded() && 4040 !args[0]->IsAccessCheckNeeded() &&
4041 args[1]->IsString()) { 4041 args[1]->IsString()) {
4042 JSObject* receiver = JSObject::cast(args[0]); 4042 JSObject* receiver = JSObject::cast(args[0]);
4043 String* key = String::cast(args[1]); 4043 String* key = String::cast(args[1]);
4044 if (receiver->HasFastProperties()) { 4044 if (receiver->HasFastProperties()) {
4045 // Attempt to use lookup cache. 4045 // Attempt to use lookup cache.
4046 Map* receiver_map = receiver->map(); 4046 Map* receiver_map = receiver->map();
4047 KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache(); 4047 KeyedLookupCache* keyed_lookup_cache = isolate->keyed_lookup_cache();
4048 int offset = keyed_lookup_cache->Lookup(receiver_map, key); 4048 int offset = keyed_lookup_cache->Lookup(receiver_map, key);
4049 if (offset != -1) { 4049 if (offset != -1) {
4050 Object* value = receiver->FastPropertyAt(offset); 4050 Object* value = receiver->FastPropertyAt(offset);
4051 return value->IsTheHole() 4051 return value->IsTheHole()
4052 ? isolate->heap()->undefined_value() 4052 ? isolate->heap()->undefined_value()
4053 : value; 4053 : value;
4054 } 4054 }
4055 // Lookup cache miss. Perform lookup and update the cache if 4055 // Lookup cache miss. Perform lookup and update the cache if
4056 // appropriate. 4056 // appropriate.
4057 LookupResult result(isolate); 4057 LookupResult result(isolate);
4058 receiver->LocalLookup(key, &result); 4058 receiver->LocalLookup(key, &result);
4059 if (result.IsField()) { 4059 if (result.IsField()) {
4060 int offset = result.GetFieldIndex(); 4060 int offset = result.GetFieldIndex();
4061 keyed_lookup_cache->Update(receiver_map, key, offset); 4061 keyed_lookup_cache->Update(receiver_map, key, offset);
4062 return receiver->FastPropertyAt(offset); 4062 return receiver->FastPropertyAt(offset);
4063 } 4063 }
4064 } else { 4064 } else {
4065 // Attempt dictionary lookup. 4065 // Attempt dictionary lookup.
4066 StringDictionary* dictionary = receiver->property_dictionary(); 4066 StringDictionary* dictionary = receiver->property_dictionary();
4067 int entry = dictionary->FindEntry(key); 4067 int entry = dictionary->FindEntry(key);
4068 if ((entry != StringDictionary::kNotFound) && 4068 if ((entry != StringDictionary::kNotFound) &&
4069 (dictionary->DetailsAt(entry).type() == NORMAL)) { 4069 (dictionary->DetailsAt(entry).type() == NORMAL)) {
4070 Object* value = dictionary->ValueAt(entry); 4070 Object* value = dictionary->ValueAt(entry);
4071 if (!receiver->IsGlobalObject()) return value; 4071 if (!receiver->IsGlobalObject()) return value;
4072 value = JSGlobalPropertyCell::cast(value)->value(); 4072 value = JSGlobalPropertyCell::cast(value)->value();
4073 if (!value->IsTheHole()) return value; 4073 if (!value->IsTheHole()) return value;
4074 // If value is the hole do the general lookup. 4074 // If value is the hole do the general lookup.
4075 } 4075 }
4076 } 4076 }
4077 } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) { 4077 } else if (FLAG_smi_only_arrays && args.at<Object>(1)->IsSmi()) {
4078 // JSObject without a string key. If the key is a Smi, check for a 4078 // JSObject without a string key. If the key is a Smi, check for a
4079 // definite out-of-bounds access to elements, which is a strong indicator 4079 // definite out-of-bounds access to elements, which is a strong indicator
4080 // that subsequent accesses will also call the runtime. Proactively 4080 // that subsequent accesses will also call the runtime. Proactively
4081 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of 4081 // transition elements to FAST_*_ELEMENTS to avoid excessive boxing of
4082 // doubles for those future calls in the case that the elements would 4082 // doubles for those future calls in the case that the elements would
4083 // become FAST_DOUBLE_ELEMENTS. 4083 // become FAST_DOUBLE_ELEMENTS.
4084 Handle<JSObject> js_object(args.at<JSObject>(0)); 4084 Handle<JSObject> js_object(args.at<JSObject>(0));
4085 ElementsKind elements_kind = js_object->GetElementsKind(); 4085 ElementsKind elements_kind = js_object->GetElementsKind();
4086 if (IsFastElementsKind(elements_kind) && 4086 if (IsFastElementsKind(elements_kind) &&
4087 !IsFastObjectElementsKind(elements_kind)) { 4087 !IsFastObjectElementsKind(elements_kind)) {
4088 FixedArrayBase* elements = js_object->elements(); 4088 FixedArrayBase* elements = js_object->elements();
4089 if (args.at<Smi>(1)->value() >= elements->length()) { 4089 if (args.at<Smi>(1)->value() >= elements->length()) {
4090 if (IsFastHoleyElementsKind(elements_kind)) { 4090 if (IsFastHoleyElementsKind(elements_kind)) {
4091 elements_kind = FAST_HOLEY_ELEMENTS; 4091 elements_kind = FAST_HOLEY_ELEMENTS;
4092 } else { 4092 } else {
4093 elements_kind = FAST_ELEMENTS; 4093 elements_kind = FAST_ELEMENTS;
4094 } 4094 }
4095 MaybeObject* maybe_object = TransitionElements(js_object, 4095 MaybeObject* maybe_object = TransitionElements(js_object,
4096 elements_kind, 4096 elements_kind,
4097 isolate); 4097 isolate);
4098 if (maybe_object->IsFailure()) return maybe_object; 4098 if (maybe_object->IsFailure()) return maybe_object;
4099 } 4099 }
4100 } 4100 }
4101 } 4101 }
4102 } else if (args[0]->IsString() && args[1]->IsSmi()) { 4102 } else if (args[0]->IsString() && args[1]->IsSmi()) {
4103 // Fast case for string indexing using [] with a smi index. 4103 // Fast case for string indexing using [] with a smi index.
4104 HandleScope scope(isolate); 4104 HandleScope scope(isolate);
4105 Handle<String> str = args.at<String>(0); 4105 Handle<String> str = args.at<String>(0);
4106 int index = args.smi_at(1); 4106 int index = args.smi_at(1);
4107 if (index >= 0 && index < str->length()) { 4107 if (index >= 0 && index < str->length()) {
4108 Handle<Object> result = GetCharAt(str, index); 4108 Handle<Object> result = GetCharAt(str, index);
4109 return *result; 4109 return *result;
4110 } 4110 }
4111 } 4111 }
4112 4112
4113 // Fall back to GetObjectProperty. 4113 // Fall back to GetObjectProperty.
4114 return Runtime::GetObjectProperty(isolate, 4114 return Runtime::GetObjectProperty(isolate,
4115 args.at<Object>(0), 4115 args.at<Object>(0),
4116 args.at<Object>(1)); 4116 args.at<Object>(1));
4117 } 4117 }
4118 4118
4119 4119
4120 static bool IsValidAccessor(Handle<Object> obj) { 4120 static bool IsValidAccessor(Handle<Object> obj) {
4121 return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull(); 4121 return obj->IsUndefined() || obj->IsSpecFunction() || obj->IsNull();
4122 } 4122 }
4123 4123
4124 4124
4125 // Implements part of 8.12.9 DefineOwnProperty. 4125 // Implements part of 8.12.9 DefineOwnProperty.
4126 // There are 3 cases that lead here: 4126 // There are 3 cases that lead here:
4127 // Step 4b - define a new accessor property. 4127 // Step 4b - define a new accessor property.
4128 // Steps 9c & 12 - replace an existing data property with an accessor property. 4128 // Steps 9c & 12 - replace an existing data property with an accessor property.
4129 // Step 12 - update an existing accessor property with an accessor or generic 4129 // Step 12 - update an existing accessor property with an accessor or generic
4130 // descriptor. 4130 // descriptor.
4131 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) { 4131 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineAccessorProperty) {
4132 ASSERT(args.length() == 5); 4132 ASSERT(args.length() == 5);
4133 HandleScope scope(isolate); 4133 HandleScope scope(isolate);
4134 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0); 4134 CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
4135 RUNTIME_ASSERT(!obj->IsNull()); 4135 RUNTIME_ASSERT(!obj->IsNull());
4136 CONVERT_ARG_HANDLE_CHECKED(String, name, 1); 4136 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4137 CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2); 4137 CONVERT_ARG_HANDLE_CHECKED(Object, getter, 2);
4138 RUNTIME_ASSERT(IsValidAccessor(getter)); 4138 RUNTIME_ASSERT(IsValidAccessor(getter));
4139 CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3); 4139 CONVERT_ARG_HANDLE_CHECKED(Object, setter, 3);
4140 RUNTIME_ASSERT(IsValidAccessor(setter)); 4140 RUNTIME_ASSERT(IsValidAccessor(setter));
4141 CONVERT_SMI_ARG_CHECKED(unchecked, 4); 4141 CONVERT_SMI_ARG_CHECKED(unchecked, 4);
4142 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); 4142 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4143 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); 4143 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4144 4144
4145 bool fast = obj->HasFastProperties(); 4145 bool fast = obj->HasFastProperties();
4146 JSObject::DefineAccessor(obj, name, getter, setter, attr); 4146 JSObject::DefineAccessor(obj, name, getter, setter, attr);
4147 if (fast) JSObject::TransformToFastProperties(obj, 0); 4147 if (fast) JSObject::TransformToFastProperties(obj, 0);
4148 return isolate->heap()->undefined_value(); 4148 return isolate->heap()->undefined_value();
4149 } 4149 }
4150 4150
4151 // Implements part of 8.12.9 DefineOwnProperty. 4151 // Implements part of 8.12.9 DefineOwnProperty.
4152 // There are 3 cases that lead here: 4152 // There are 3 cases that lead here:
4153 // Step 4a - define a new data property. 4153 // Step 4a - define a new data property.
4154 // Steps 9b & 12 - replace an existing accessor property with a data property. 4154 // Steps 9b & 12 - replace an existing accessor property with a data property.
4155 // Step 12 - update an existing data property with a data or generic 4155 // Step 12 - update an existing data property with a data or generic
4156 // descriptor. 4156 // descriptor.
4157 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) { 4157 RUNTIME_FUNCTION(MaybeObject*, Runtime_DefineOrRedefineDataProperty) {
4158 ASSERT(args.length() == 4); 4158 ASSERT(args.length() == 4);
4159 HandleScope scope(isolate); 4159 HandleScope scope(isolate);
4160 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0); 4160 CONVERT_ARG_HANDLE_CHECKED(JSObject, js_object, 0);
4161 CONVERT_ARG_HANDLE_CHECKED(String, name, 1); 4161 CONVERT_ARG_HANDLE_CHECKED(String, name, 1);
4162 CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2); 4162 CONVERT_ARG_HANDLE_CHECKED(Object, obj_value, 2);
4163 CONVERT_SMI_ARG_CHECKED(unchecked, 3); 4163 CONVERT_SMI_ARG_CHECKED(unchecked, 3);
4164 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); 4164 RUNTIME_ASSERT((unchecked & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4165 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked); 4165 PropertyAttributes attr = static_cast<PropertyAttributes>(unchecked);
4166 4166
4167 LookupResult result(isolate); 4167 LookupResult result(isolate);
4168 js_object->LocalLookupRealNamedProperty(*name, &result); 4168 js_object->LocalLookupRealNamedProperty(*name, &result);
4169 4169
4170 // Special case for callback properties. 4170 // Special case for callback properties.
4171 if (result.IsPropertyCallbacks()) { 4171 if (result.IsPropertyCallbacks()) {
4172 Object* callback = result.GetCallbackObject(); 4172 Object* callback = result.GetCallbackObject();
4173 // To be compatible with Safari we do not change the value on API objects 4173 // To be compatible with Safari we do not change the value on API objects
4174 // in Object.defineProperty(). Firefox disagrees here, and actually changes 4174 // in Object.defineProperty(). Firefox disagrees here, and actually changes
4175 // the value. 4175 // the value.
4176 if (callback->IsAccessorInfo()) { 4176 if (callback->IsAccessorInfo()) {
4177 return isolate->heap()->undefined_value(); 4177 return isolate->heap()->undefined_value();
4178 } 4178 }
4179 // Avoid redefining foreign callback as data property, just use the stored 4179 // Avoid redefining foreign callback as data property, just use the stored
4180 // setter to update the value instead. 4180 // setter to update the value instead.
4181 // TODO(mstarzinger): So far this only works if property attributes don't 4181 // TODO(mstarzinger): So far this only works if property attributes don't
4182 // change, this should be fixed once we cleanup the underlying code. 4182 // change, this should be fixed once we cleanup the underlying code.
4183 if (callback->IsForeign() && result.GetAttributes() == attr) { 4183 if (callback->IsForeign() && result.GetAttributes() == attr) {
4184 return js_object->SetPropertyWithCallback(callback, 4184 return js_object->SetPropertyWithCallback(callback,
4185 *name, 4185 *name,
4186 *obj_value, 4186 *obj_value,
4187 result.holder(), 4187 result.holder(),
4188 kStrictMode); 4188 kStrictMode);
4189 } 4189 }
4190 } 4190 }
4191 4191
4192 // Take special care when attributes are different and there is already 4192 // Take special care when attributes are different and there is already
4193 // a property. For simplicity we normalize the property which enables us 4193 // a property. For simplicity we normalize the property which enables us
4194 // to not worry about changing the instance_descriptor and creating a new 4194 // to not worry about changing the instance_descriptor and creating a new
4195 // map. The current version of SetObjectProperty does not handle attributes 4195 // map. The current version of SetObjectProperty does not handle attributes
4196 // correctly in the case where a property is a field and is reset with 4196 // correctly in the case where a property is a field and is reset with
4197 // new attributes. 4197 // new attributes.
4198 if (result.IsFound() && 4198 if (result.IsFound() &&
4199 (attr != result.GetAttributes() || result.IsPropertyCallbacks())) { 4199 (attr != result.GetAttributes() || result.IsPropertyCallbacks())) {
4200 // New attributes - normalize to avoid writing to instance descriptor 4200 // New attributes - normalize to avoid writing to instance descriptor
4201 if (js_object->IsJSGlobalProxy()) { 4201 if (js_object->IsJSGlobalProxy()) {
4202 // Since the result is a property, the prototype will exist so 4202 // Since the result is a property, the prototype will exist so
4203 // we don't have to check for null. 4203 // we don't have to check for null.
4204 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype())); 4204 js_object = Handle<JSObject>(JSObject::cast(js_object->GetPrototype()));
4205 } 4205 }
4206 JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0); 4206 JSObject::NormalizeProperties(js_object, CLEAR_INOBJECT_PROPERTIES, 0);
4207 // Use IgnoreAttributes version since a readonly property may be 4207 // Use IgnoreAttributes version since a readonly property may be
4208 // overridden and SetProperty does not allow this. 4208 // overridden and SetProperty does not allow this.
4209 return js_object->SetLocalPropertyIgnoreAttributes(*name, 4209 return js_object->SetLocalPropertyIgnoreAttributes(*name,
4210 *obj_value, 4210 *obj_value,
4211 attr); 4211 attr);
4212 } 4212 }
4213 4213
4214 return Runtime::ForceSetObjectProperty(isolate, 4214 return Runtime::ForceSetObjectProperty(isolate,
4215 js_object, 4215 js_object,
4216 name, 4216 name,
4217 obj_value, 4217 obj_value,
4218 attr); 4218 attr);
4219 } 4219 }
4220 4220
4221 4221
4222 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate, 4222 MaybeObject* Runtime::SetObjectProperty(Isolate* isolate,
4223 Handle<Object> object, 4223 Handle<Object> object,
4224 Handle<Object> key, 4224 Handle<Object> key,
4225 Handle<Object> value, 4225 Handle<Object> value,
4226 PropertyAttributes attr, 4226 PropertyAttributes attr,
4227 StrictModeFlag strict_mode) { 4227 StrictModeFlag strict_mode) {
4228 SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY; 4228 SetPropertyMode set_mode = attr == NONE ? SET_PROPERTY : DEFINE_PROPERTY;
4229 HandleScope scope(isolate); 4229 HandleScope scope(isolate);
4230 4230
4231 if (object->IsUndefined() || object->IsNull()) { 4231 if (object->IsUndefined() || object->IsNull()) {
4232 Handle<Object> args[2] = { key, object }; 4232 Handle<Object> args[2] = { key, object };
4233 Handle<Object> error = 4233 Handle<Object> error =
4234 isolate->factory()->NewTypeError("non_object_property_store", 4234 isolate->factory()->NewTypeError("non_object_property_store",
4235 HandleVector(args, 2)); 4235 HandleVector(args, 2));
4236 return isolate->Throw(*error); 4236 return isolate->Throw(*error);
4237 } 4237 }
4238 4238
4239 if (object->IsJSProxy()) { 4239 if (object->IsJSProxy()) {
4240 bool has_pending_exception = false; 4240 bool has_pending_exception = false;
4241 Handle<Object> name = Execution::ToString(key, &has_pending_exception); 4241 Handle<Object> name = Execution::ToString(key, &has_pending_exception);
4242 if (has_pending_exception) return Failure::Exception(); 4242 if (has_pending_exception) return Failure::Exception();
4243 return JSProxy::cast(*object)->SetProperty( 4243 return JSProxy::cast(*object)->SetProperty(
4244 String::cast(*name), *value, attr, strict_mode); 4244 String::cast(*name), *value, attr, strict_mode);
4245 } 4245 }
4246 4246
4247 // If the object isn't a JavaScript object, we ignore the store. 4247 // If the object isn't a JavaScript object, we ignore the store.
4248 if (!object->IsJSObject()) return *value; 4248 if (!object->IsJSObject()) return *value;
4249 4249
4250 Handle<JSObject> js_object = Handle<JSObject>::cast(object); 4250 Handle<JSObject> js_object = Handle<JSObject>::cast(object);
4251 4251
4252 // Check if the given key is an array index. 4252 // Check if the given key is an array index.
4253 uint32_t index; 4253 uint32_t index;
4254 if (key->ToArrayIndex(&index)) { 4254 if (key->ToArrayIndex(&index)) {
4255 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters 4255 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4256 // of a string using [] notation. We need to support this too in 4256 // of a string using [] notation. We need to support this too in
4257 // JavaScript. 4257 // JavaScript.
4258 // In the case of a String object we just need to redirect the assignment to 4258 // In the case of a String object we just need to redirect the assignment to
4259 // the underlying string if the index is in range. Since the underlying 4259 // the underlying string if the index is in range. Since the underlying
4260 // string does nothing with the assignment then we can ignore such 4260 // string does nothing with the assignment then we can ignore such
4261 // assignments. 4261 // assignments.
4262 if (js_object->IsStringObjectWithCharacterAt(index)) { 4262 if (js_object->IsStringObjectWithCharacterAt(index)) {
4263 return *value; 4263 return *value;
4264 } 4264 }
4265 4265
4266 js_object->ValidateElements(); 4266 js_object->ValidateElements();
4267 Handle<Object> result = JSObject::SetElement( 4267 Handle<Object> result = JSObject::SetElement(
4268 js_object, index, value, attr, strict_mode, set_mode); 4268 js_object, index, value, attr, strict_mode, set_mode);
4269 js_object->ValidateElements(); 4269 js_object->ValidateElements();
4270 if (result.is_null()) return Failure::Exception(); 4270 if (result.is_null()) return Failure::Exception();
4271 return *value; 4271 return *value;
4272 } 4272 }
4273 4273
4274 if (key->IsString()) { 4274 if (key->IsString()) {
4275 Handle<Object> result; 4275 Handle<Object> result;
4276 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 4276 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4277 result = JSObject::SetElement( 4277 result = JSObject::SetElement(
4278 js_object, index, value, attr, strict_mode, set_mode); 4278 js_object, index, value, attr, strict_mode, set_mode);
4279 } else { 4279 } else {
4280 Handle<String> key_string = Handle<String>::cast(key); 4280 Handle<String> key_string = Handle<String>::cast(key);
4281 key_string->TryFlatten(); 4281 key_string->TryFlatten();
4282 result = JSReceiver::SetProperty( 4282 result = JSReceiver::SetProperty(
4283 js_object, key_string, value, attr, strict_mode); 4283 js_object, key_string, value, attr, strict_mode);
4284 } 4284 }
4285 if (result.is_null()) return Failure::Exception(); 4285 if (result.is_null()) return Failure::Exception();
4286 return *value; 4286 return *value;
4287 } 4287 }
4288 4288
4289 // Call-back into JavaScript to convert the key to a string. 4289 // Call-back into JavaScript to convert the key to a string.
4290 bool has_pending_exception = false; 4290 bool has_pending_exception = false;
4291 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 4291 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4292 if (has_pending_exception) return Failure::Exception(); 4292 if (has_pending_exception) return Failure::Exception();
4293 Handle<String> name = Handle<String>::cast(converted); 4293 Handle<String> name = Handle<String>::cast(converted);
4294 4294
4295 if (name->AsArrayIndex(&index)) { 4295 if (name->AsArrayIndex(&index)) {
4296 return js_object->SetElement( 4296 return js_object->SetElement(
4297 index, *value, attr, strict_mode, true, set_mode); 4297 index, *value, attr, strict_mode, true, set_mode);
4298 } else { 4298 } else {
4299 return js_object->SetProperty(*name, *value, attr, strict_mode); 4299 return js_object->SetProperty(*name, *value, attr, strict_mode);
4300 } 4300 }
4301 } 4301 }
4302 4302
4303 4303
4304 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate, 4304 MaybeObject* Runtime::ForceSetObjectProperty(Isolate* isolate,
4305 Handle<JSObject> js_object, 4305 Handle<JSObject> js_object,
4306 Handle<Object> key, 4306 Handle<Object> key,
4307 Handle<Object> value, 4307 Handle<Object> value,
4308 PropertyAttributes attr) { 4308 PropertyAttributes attr) {
4309 HandleScope scope(isolate); 4309 HandleScope scope(isolate);
4310 4310
4311 // Check if the given key is an array index. 4311 // Check if the given key is an array index.
4312 uint32_t index; 4312 uint32_t index;
4313 if (key->ToArrayIndex(&index)) { 4313 if (key->ToArrayIndex(&index)) {
4314 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters 4314 // In Firefox/SpiderMonkey, Safari and Opera you can access the characters
4315 // of a string using [] notation. We need to support this too in 4315 // of a string using [] notation. We need to support this too in
4316 // JavaScript. 4316 // JavaScript.
4317 // In the case of a String object we just need to redirect the assignment to 4317 // In the case of a String object we just need to redirect the assignment to
4318 // the underlying string if the index is in range. Since the underlying 4318 // the underlying string if the index is in range. Since the underlying
4319 // string does nothing with the assignment then we can ignore such 4319 // string does nothing with the assignment then we can ignore such
4320 // assignments. 4320 // assignments.
4321 if (js_object->IsStringObjectWithCharacterAt(index)) { 4321 if (js_object->IsStringObjectWithCharacterAt(index)) {
4322 return *value; 4322 return *value;
4323 } 4323 }
4324 4324
4325 return js_object->SetElement( 4325 return js_object->SetElement(
4326 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); 4326 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4327 } 4327 }
4328 4328
4329 if (key->IsString()) { 4329 if (key->IsString()) {
4330 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 4330 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
4331 return js_object->SetElement( 4331 return js_object->SetElement(
4332 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); 4332 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4333 } else { 4333 } else {
4334 Handle<String> key_string = Handle<String>::cast(key); 4334 Handle<String> key_string = Handle<String>::cast(key);
4335 key_string->TryFlatten(); 4335 key_string->TryFlatten();
4336 return js_object->SetLocalPropertyIgnoreAttributes(*key_string, 4336 return js_object->SetLocalPropertyIgnoreAttributes(*key_string,
4337 *value, 4337 *value,
4338 attr); 4338 attr);
4339 } 4339 }
4340 } 4340 }
4341 4341
4342 // Call-back into JavaScript to convert the key to a string. 4342 // Call-back into JavaScript to convert the key to a string.
4343 bool has_pending_exception = false; 4343 bool has_pending_exception = false;
4344 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 4344 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4345 if (has_pending_exception) return Failure::Exception(); 4345 if (has_pending_exception) return Failure::Exception();
4346 Handle<String> name = Handle<String>::cast(converted); 4346 Handle<String> name = Handle<String>::cast(converted);
4347 4347
4348 if (name->AsArrayIndex(&index)) { 4348 if (name->AsArrayIndex(&index)) {
4349 return js_object->SetElement( 4349 return js_object->SetElement(
4350 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY); 4350 index, *value, attr, kNonStrictMode, false, DEFINE_PROPERTY);
4351 } else { 4351 } else {
4352 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr); 4352 return js_object->SetLocalPropertyIgnoreAttributes(*name, *value, attr);
4353 } 4353 }
4354 } 4354 }
4355 4355
4356 4356
4357 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate, 4357 MaybeObject* Runtime::ForceDeleteObjectProperty(Isolate* isolate,
4358 Handle<JSReceiver> receiver, 4358 Handle<JSReceiver> receiver,
4359 Handle<Object> key) { 4359 Handle<Object> key) {
4360 HandleScope scope(isolate); 4360 HandleScope scope(isolate);
4361 4361
4362 // Check if the given key is an array index. 4362 // Check if the given key is an array index.
4363 uint32_t index; 4363 uint32_t index;
4364 if (key->ToArrayIndex(&index)) { 4364 if (key->ToArrayIndex(&index)) {
4365 // In Firefox/SpiderMonkey, Safari and Opera you can access the 4365 // In Firefox/SpiderMonkey, Safari and Opera you can access the
4366 // characters of a string using [] notation. In the case of a 4366 // characters of a string using [] notation. In the case of a
4367 // String object we just need to redirect the deletion to the 4367 // String object we just need to redirect the deletion to the
4368 // underlying string if the index is in range. Since the 4368 // underlying string if the index is in range. Since the
4369 // underlying string does nothing with the deletion, we can ignore 4369 // underlying string does nothing with the deletion, we can ignore
4370 // such deletions. 4370 // such deletions.
4371 if (receiver->IsStringObjectWithCharacterAt(index)) { 4371 if (receiver->IsStringObjectWithCharacterAt(index)) {
4372 return isolate->heap()->true_value(); 4372 return isolate->heap()->true_value();
4373 } 4373 }
4374 4374
4375 return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION); 4375 return receiver->DeleteElement(index, JSReceiver::FORCE_DELETION);
4376 } 4376 }
4377 4377
4378 Handle<String> key_string; 4378 Handle<String> key_string;
4379 if (key->IsString()) { 4379 if (key->IsString()) {
4380 key_string = Handle<String>::cast(key); 4380 key_string = Handle<String>::cast(key);
4381 } else { 4381 } else {
4382 // Call-back into JavaScript to convert the key to a string. 4382 // Call-back into JavaScript to convert the key to a string.
4383 bool has_pending_exception = false; 4383 bool has_pending_exception = false;
4384 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 4384 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
4385 if (has_pending_exception) return Failure::Exception(); 4385 if (has_pending_exception) return Failure::Exception();
4386 key_string = Handle<String>::cast(converted); 4386 key_string = Handle<String>::cast(converted);
4387 } 4387 }
4388 4388
4389 key_string->TryFlatten(); 4389 key_string->TryFlatten();
4390 return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION); 4390 return receiver->DeleteProperty(*key_string, JSReceiver::FORCE_DELETION);
4391 } 4391 }
4392 4392
4393 4393
4394 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) { 4394 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetProperty) {
4395 NoHandleAllocation ha; 4395 NoHandleAllocation ha;
4396 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5); 4396 RUNTIME_ASSERT(args.length() == 4 || args.length() == 5);
4397 4397
4398 Handle<Object> object = args.at<Object>(0); 4398 Handle<Object> object = args.at<Object>(0);
4399 Handle<Object> key = args.at<Object>(1); 4399 Handle<Object> key = args.at<Object>(1);
4400 Handle<Object> value = args.at<Object>(2); 4400 Handle<Object> value = args.at<Object>(2);
4401 CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3); 4401 CONVERT_SMI_ARG_CHECKED(unchecked_attributes, 3);
4402 RUNTIME_ASSERT( 4402 RUNTIME_ASSERT(
4403 (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0); 4403 (unchecked_attributes & ~(READ_ONLY | DONT_ENUM | DONT_DELETE)) == 0);
4404 // Compute attributes. 4404 // Compute attributes.
4405 PropertyAttributes attributes = 4405 PropertyAttributes attributes =
4406 static_cast<PropertyAttributes>(unchecked_attributes); 4406 static_cast<PropertyAttributes>(unchecked_attributes);
4407 4407
4408 StrictModeFlag strict_mode = kNonStrictMode; 4408 StrictModeFlag strict_mode = kNonStrictMode;
4409 if (args.length() == 5) { 4409 if (args.length() == 5) {
4410 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4); 4410 CONVERT_STRICT_MODE_ARG_CHECKED(strict_mode_flag, 4);
4411 strict_mode = strict_mode_flag; 4411 strict_mode = strict_mode_flag;
4412 } 4412 }
4413 4413
4414 return Runtime::SetObjectProperty(isolate, 4414 return Runtime::SetObjectProperty(isolate,
4415 object, 4415 object,
4416 key, 4416 key,
4417 value, 4417 value,
4418 attributes, 4418 attributes,
4419 strict_mode); 4419 strict_mode);
4420 } 4420 }
4421 4421
4422 4422
4423 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) { 4423 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsSmiToDouble) {
4424 NoHandleAllocation ha; 4424 NoHandleAllocation ha;
4425 RUNTIME_ASSERT(args.length() == 1); 4425 RUNTIME_ASSERT(args.length() == 1);
4426 Handle<Object> object = args.at<Object>(0); 4426 Handle<Object> object = args.at<Object>(0);
4427 if (object->IsJSObject()) { 4427 if (object->IsJSObject()) {
4428 Handle<JSObject> js_object(Handle<JSObject>::cast(object)); 4428 Handle<JSObject> js_object(Handle<JSObject>::cast(object));
4429 ElementsKind new_kind = js_object->HasFastHoleyElements() 4429 ElementsKind new_kind = js_object->HasFastHoleyElements()
4430 ? FAST_HOLEY_DOUBLE_ELEMENTS 4430 ? FAST_HOLEY_DOUBLE_ELEMENTS
4431 : FAST_DOUBLE_ELEMENTS; 4431 : FAST_DOUBLE_ELEMENTS;
4432 return TransitionElements(object, new_kind, isolate); 4432 return TransitionElements(object, new_kind, isolate);
4433 } else { 4433 } else {
4434 return *object; 4434 return *object;
4435 } 4435 }
4436 } 4436 }
4437 4437
4438 4438
4439 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) { 4439 RUNTIME_FUNCTION(MaybeObject*, Runtime_TransitionElementsDoubleToObject) {
4440 NoHandleAllocation ha; 4440 NoHandleAllocation ha;
4441 RUNTIME_ASSERT(args.length() == 1); 4441 RUNTIME_ASSERT(args.length() == 1);
4442 Handle<Object> object = args.at<Object>(0); 4442 Handle<Object> object = args.at<Object>(0);
4443 if (object->IsJSObject()) { 4443 if (object->IsJSObject()) {
4444 Handle<JSObject> js_object(Handle<JSObject>::cast(object)); 4444 Handle<JSObject> js_object(Handle<JSObject>::cast(object));
4445 ElementsKind new_kind = js_object->HasFastHoleyElements() 4445 ElementsKind new_kind = js_object->HasFastHoleyElements()
4446 ? FAST_HOLEY_ELEMENTS 4446 ? FAST_HOLEY_ELEMENTS
4447 : FAST_ELEMENTS; 4447 : FAST_ELEMENTS;
4448 return TransitionElements(object, new_kind, isolate); 4448 return TransitionElements(object, new_kind, isolate);
4449 } else { 4449 } else {
4450 return *object; 4450 return *object;
4451 } 4451 }
4452 } 4452 }
4453 4453
4454 4454
4455 // Set the native flag on the function. 4455 // Set the native flag on the function.
4456 // This is used to decide if we should transform null and undefined 4456 // This is used to decide if we should transform null and undefined
4457 // into the global object when doing call and apply. 4457 // into the global object when doing call and apply.
4458 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) { 4458 RUNTIME_FUNCTION(MaybeObject*, Runtime_SetNativeFlag) {
4459 NoHandleAllocation ha; 4459 NoHandleAllocation ha;
4460 RUNTIME_ASSERT(args.length() == 1); 4460 RUNTIME_ASSERT(args.length() == 1);
4461 4461
4462 Handle<Object> object = args.at<Object>(0); 4462 Handle<Object> object = args.at<Object>(0);
4463 4463
4464 if (object->IsJSFunction()) { 4464 if (object->IsJSFunction()) {