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

Side by Side Diff: src/runtime.cc

Issue 48006: Reapply revisions 1432, 1433, 1469 and 1472 while fixing issue 279. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 26 matching lines...) Expand all
37 #include "dateparser.h" 37 #include "dateparser.h"
38 #include "dateparser-inl.h" 38 #include "dateparser-inl.h"
39 #include "debug.h" 39 #include "debug.h"
40 #include "execution.h" 40 #include "execution.h"
41 #include "jsregexp.h" 41 #include "jsregexp.h"
42 #include "platform.h" 42 #include "platform.h"
43 #include "runtime.h" 43 #include "runtime.h"
44 #include "scopeinfo.h" 44 #include "scopeinfo.h"
45 #include "v8threads.h" 45 #include "v8threads.h"
46 #include "smart-pointer.h" 46 #include "smart-pointer.h"
47 #include "parser.h"
47 48
48 namespace v8 { namespace internal { 49 namespace v8 { namespace internal {
49 50
50 51
51 #define RUNTIME_ASSERT(value) do { \ 52 #define RUNTIME_ASSERT(value) do { \
52 if (!(value)) return IllegalOperation(); \ 53 if (!(value)) return IllegalOperation(); \
53 } while (false) 54 } while (false)
54 55
55 // Cast the given object to a value of the specified type and store 56 // Cast the given object to a value of the specified type and store
56 // it in a variable with the given name. If the object is not of the 57 // it in a variable with the given name. If the object is not of the
57 // expected type call IllegalOperation and return. 58 // expected type call IllegalOperation and return.
58 #define CONVERT_CHECKED(Type, name, obj) \ 59 #define CONVERT_CHECKED(Type, name, obj) \
59 RUNTIME_ASSERT(obj->Is##Type()); \ 60 RUNTIME_ASSERT(obj->Is##Type()); \
60 Type* name = Type::cast(obj); 61 Type* name = Type::cast(obj);
61 62
62 #define CONVERT_ARG_CHECKED(Type, name, index) \ 63 #define CONVERT_ARG_CHECKED(Type, name, index) \
63 RUNTIME_ASSERT(args[index]->Is##Type()); \ 64 RUNTIME_ASSERT(args[index]->Is##Type()); \
64 Handle<Type> name = args.at<Type>(index); 65 Handle<Type> name = args.at<Type>(index);
65 66
66 // Cast the given object to a boolean and store it in a variable with 67 // Cast the given object to a boolean and store it in a variable with
67 // the given name. If the object is not a boolean call IllegalOperation 68 // the given name. If the object is not a boolean call IllegalOperation
68 // and return. 69 // and return.
69 #define CONVERT_BOOLEAN_CHECKED(name, obj) \ 70 #define CONVERT_BOOLEAN_CHECKED(name, obj) \
70 RUNTIME_ASSERT(obj->IsBoolean()); \ 71 RUNTIME_ASSERT(obj->IsBoolean()); \
71 bool name = (obj)->IsTrue(); 72 bool name = (obj)->IsTrue();
72 73
74 // Cast the given object to a Smi and store its value in an int variable
75 // with the given name. If the object is not a Smi call IllegalOperation
76 // and return.
77 #define CONVERT_SMI_CHECKED(name, obj) \
78 RUNTIME_ASSERT(obj->IsSmi()); \
79 int name = Smi::cast(obj)->value();
80
73 // Cast the given object to a double and store it in a variable with 81 // Cast the given object to a double and store it in a variable with
74 // the given name. If the object is not a number (as opposed to 82 // the given name. If the object is not a number (as opposed to
75 // the number not-a-number) call IllegalOperation and return. 83 // the number not-a-number) call IllegalOperation and return.
76 #define CONVERT_DOUBLE_CHECKED(name, obj) \ 84 #define CONVERT_DOUBLE_CHECKED(name, obj) \
77 RUNTIME_ASSERT(obj->IsNumber()); \ 85 RUNTIME_ASSERT(obj->IsNumber()); \
78 double name = (obj)->Number(); 86 double name = (obj)->Number();
79 87
80 // Call the specified converter on the object *comand store the result in 88 // Call the specified converter on the object *comand store the result in
81 // a variable of the specified type with the given name. If the 89 // a variable of the specified type with the given name. If the
82 // object is not a Number call IllegalOperation and return. 90 // object is not a Number call IllegalOperation and return.
83 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \ 91 #define CONVERT_NUMBER_CHECKED(type, name, Type, obj) \
84 RUNTIME_ASSERT(obj->IsNumber()); \ 92 RUNTIME_ASSERT(obj->IsNumber()); \
85 type name = NumberTo##Type(obj); 93 type name = NumberTo##Type(obj);
86 94
87 // Non-reentrant string buffer for efficient general use in this file. 95 // Non-reentrant string buffer for efficient general use in this file.
88 static StaticResource<StringInputBuffer> runtime_string_input_buffer; 96 static StaticResource<StringInputBuffer> runtime_string_input_buffer;
89 97
90 98
91 static Object* IllegalOperation() { 99 static Object* IllegalOperation() {
92 return Top::Throw(Heap::illegal_access_symbol()); 100 return Top::Throw(Heap::illegal_access_symbol());
93 } 101 }
94 102
95 103
96 static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) { 104 static Object* DeepCopyBoilerplate(JSObject* boilerplate) {
105 StackLimitCheck check;
106 if (check.HasOverflowed()) return Top::StackOverflow();
107
108 Object* result = Heap::CopyJSObject(boilerplate);
109 if (result->IsFailure()) return result;
110 JSObject* copy = JSObject::cast(result);
111
112 // Deep copy local properties.
113 if (copy->HasFastProperties()) {
114 FixedArray* properties = copy->properties();
115 WriteBarrierMode mode = properties->GetWriteBarrierMode();
116 for (int i = 0; i < properties->length(); i++) {
117 Object* value = properties->get(i);
118 if (value->IsJSObject()) {
119 JSObject* jsObject = JSObject::cast(value);
120 result = DeepCopyBoilerplate(jsObject);
121 if (result->IsFailure()) return result;
122 properties->set(i, result, mode);
123 }
124 }
125 mode = copy->GetWriteBarrierMode();
126 for (int i = 0; i < copy->map()->inobject_properties(); i++) {
127 Object* value = copy->InObjectPropertyAt(i);
128 if (value->IsJSObject()) {
129 JSObject* jsObject = JSObject::cast(value);
130 result = DeepCopyBoilerplate(jsObject);
131 if (result->IsFailure()) return result;
132 copy->InObjectPropertyAtPut(i, result, mode);
133 }
134 }
135 } else {
136 result = Heap::AllocateFixedArray(copy->NumberOfLocalProperties(NONE));
137 if (result->IsFailure()) return result;
138 FixedArray* names = FixedArray::cast(result);
139 copy->GetLocalPropertyNames(names, 0);
140 for (int i = 0; i < names->length(); i++) {
141 ASSERT(names->get(i)->IsString());
142 String* keyString = String::cast(names->get(i));
143 PropertyAttributes attributes = copy->GetLocalPropertyAttribute(keyString) ;
144 // Only deep copy fields from the object literal expression.
145 // In particular, don't try to copy the length attribute of
146 // an array.
147 if (attributes != NONE) continue;
148 Object* value = copy->GetProperty(keyString, &attributes);
149 ASSERT(!value->IsFailure());
150 if (value->IsJSObject()) {
151 JSObject* jsObject = JSObject::cast(value);
152 result = DeepCopyBoilerplate(jsObject);
153 if (result->IsFailure()) return result;
154 result = copy->SetProperty(keyString, result, NONE);
155 if (result->IsFailure()) return result;
156 }
157 }
158 }
159
160 // Deep copy local elements.
161 if (copy->HasFastElements()) {
162 FixedArray* elements = copy->elements();
163 WriteBarrierMode mode = elements->GetWriteBarrierMode();
164 for (int i = 0; i < elements->length(); i++) {
165 Object* value = elements->get(i);
166 if (value->IsJSObject()) {
167 JSObject* jsObject = JSObject::cast(value);
168 result = DeepCopyBoilerplate(jsObject);
169 if (result->IsFailure()) return result;
170 elements->set(i, result, mode);
171 }
172 }
173 } else {
174 Dictionary* element_dictionary = copy->element_dictionary();
175 int capacity = element_dictionary->Capacity();
176 for (int i = 0; i < capacity; i++) {
177 Object* k = element_dictionary->KeyAt(i);
178 if (element_dictionary->IsKey(k)) {
179 Object* value = element_dictionary->ValueAt(i);
180 if (value->IsJSObject()) {
181 JSObject* jsObject = JSObject::cast(value);
182 result = DeepCopyBoilerplate(jsObject);
183 if (result->IsFailure()) return result;
184 element_dictionary->ValueAtPut(i, result);
185 }
186 }
187 }
188 }
189 return copy;
190 }
191
192
193 static Object* Runtime_CloneLiteralBoilerplate(Arguments args) {
194 CONVERT_CHECKED(JSObject, boilerplate, args[0]);
195 return DeepCopyBoilerplate(boilerplate);
196 }
197
198
199 static Object* Runtime_CloneShallowLiteralBoilerplate(Arguments args) {
97 CONVERT_CHECKED(JSObject, boilerplate, args[0]); 200 CONVERT_CHECKED(JSObject, boilerplate, args[0]);
98 return Heap::CopyJSObject(boilerplate); 201 return Heap::CopyJSObject(boilerplate);
99 } 202 }
100 203
101 204
102 static Handle<Map> ComputeObjectLiteralMap( 205 static Handle<Map> ComputeObjectLiteralMap(
103 Handle<Context> context, 206 Handle<Context> context,
104 Handle<FixedArray> constant_properties, 207 Handle<FixedArray> constant_properties,
105 bool* is_result_from_cache) { 208 bool* is_result_from_cache) {
106 int number_of_properties = constant_properties->length() / 2; 209 int number_of_properties = constant_properties->length() / 2;
(...skipping 18 matching lines...) Expand all
125 return Factory::ObjectLiteralMapFromCache(context, keys); 228 return Factory::ObjectLiteralMapFromCache(context, keys);
126 } 229 }
127 } 230 }
128 *is_result_from_cache = false; 231 *is_result_from_cache = false;
129 return Factory::CopyMap( 232 return Factory::CopyMap(
130 Handle<Map>(context->object_function()->initial_map()), 233 Handle<Map>(context->object_function()->initial_map()),
131 number_of_properties); 234 number_of_properties);
132 } 235 }
133 236
134 237
135 static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) { 238 static Handle<Object> CreateLiteralBoilerplate(
136 HandleScope scope; 239 Handle<FixedArray> literals,
137 ASSERT(args.length() == 3); 240 Handle<FixedArray> constant_properties);
138 // Copy the arguments.
139 Handle<FixedArray> literals = args.at<FixedArray>(0);
140 int literals_index = Smi::cast(args[1])->value();
141 Handle<FixedArray> constant_properties = args.at<FixedArray>(2);
142 241
242
243 static Handle<Object> CreateObjectLiteralBoilerplate(
244 Handle<FixedArray> literals,
245 Handle<FixedArray> constant_properties) {
143 // Get the global context from the literals array. This is the 246 // Get the global context from the literals array. This is the
144 // context in which the function was created and we use the object 247 // context in which the function was created and we use the object
145 // function from this context to create the object literal. We do 248 // function from this context to create the object literal. We do
146 // not use the object function from the current global context 249 // not use the object function from the current global context
147 // because this might be the object function from another context 250 // because this might be the object function from another context
148 // which we should not have access to. 251 // which we should not have access to.
149 Handle<Context> context = 252 Handle<Context> context =
150 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals)); 253 Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));
151 254
152 bool is_result_from_cache; 255 bool is_result_from_cache;
153 Handle<Map> map = ComputeObjectLiteralMap(context, 256 Handle<Map> map = ComputeObjectLiteralMap(context,
154 constant_properties, 257 constant_properties,
155 &is_result_from_cache); 258 &is_result_from_cache);
156 259
157 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map); 260 Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);
158 { // Add the constant properties to the boilerplate. 261 { // Add the constant properties to the boilerplate.
159 int length = constant_properties->length(); 262 int length = constant_properties->length();
160 OptimizedObjectForAddingMultipleProperties opt(boilerplate, 263 OptimizedObjectForAddingMultipleProperties opt(boilerplate,
161 !is_result_from_cache); 264 !is_result_from_cache);
162 for (int index = 0; index < length; index +=2) { 265 for (int index = 0; index < length; index +=2) {
163 Handle<Object> key(constant_properties->get(index+0)); 266 Handle<Object> key(constant_properties->get(index+0));
164 Handle<Object> value(constant_properties->get(index+1)); 267 Handle<Object> value(constant_properties->get(index+1));
268 if (value->IsFixedArray()) {
269 // The value contains the constant_properties of a
270 // simple object literal.
271 Handle<FixedArray> array = Handle<FixedArray>::cast(value);
272 value = CreateLiteralBoilerplate(literals, array);
273 if (value.is_null()) return value;
274 }
165 Handle<Object> result; 275 Handle<Object> result;
166 uint32_t element_index = 0; 276 uint32_t element_index = 0;
167 if (key->IsSymbol()) { 277 if (key->IsSymbol()) {
168 // If key is a symbol it is not an array element. 278 // If key is a symbol it is not an array element.
169 Handle<String> name(String::cast(*key)); 279 Handle<String> name(String::cast(*key));
170 ASSERT(!name->AsArrayIndex(&element_index)); 280 ASSERT(!name->AsArrayIndex(&element_index));
171 result = SetProperty(boilerplate, name, value, NONE); 281 result = SetProperty(boilerplate, name, value, NONE);
172 } else if (Array::IndexFromObject(*key, &element_index)) { 282 } else if (Array::IndexFromObject(*key, &element_index)) {
173 // Array index (uint32). 283 // Array index (uint32).
174 result = SetElement(boilerplate, element_index, value); 284 result = SetElement(boilerplate, element_index, value);
175 } else { 285 } else {
176 // Non-uint32 number. 286 // Non-uint32 number.
177 ASSERT(key->IsNumber()); 287 ASSERT(key->IsNumber());
178 double num = key->Number(); 288 double num = key->Number();
179 char arr[100]; 289 char arr[100];
180 Vector<char> buffer(arr, ARRAY_SIZE(arr)); 290 Vector<char> buffer(arr, ARRAY_SIZE(arr));
181 const char* str = DoubleToCString(num, buffer); 291 const char* str = DoubleToCString(num, buffer);
182 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str)); 292 Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));
183 result = SetProperty(boilerplate, name, value, NONE); 293 result = SetProperty(boilerplate, name, value, NONE);
184 } 294 }
185 // If setting the property on the boilerplate throws an 295 // If setting the property on the boilerplate throws an
186 // exception, the exception is converted to an empty handle in 296 // exception, the exception is converted to an empty handle in
187 // the handle based operations. In that case, we need to 297 // the handle based operations. In that case, we need to
188 // convert back to an exception. 298 // convert back to an exception.
189 if (result.is_null()) return Failure::Exception(); 299 if (result.is_null()) return result;
190 } 300 }
191 } 301 }
192 302
193 // Update the functions literal and return the boilerplate. 303 return boilerplate;
194 literals->set(literals_index, *boilerplate);
195
196 return *boilerplate;
197 } 304 }
198 305
199 306
200 static Object* Runtime_CreateArrayLiteral(Arguments args) { 307 static Handle<Object> CreateArrayLiteralBoilerplate(
308 Handle<FixedArray> literals,
309 Handle<FixedArray> elements) {
310 // Create the JSArray.
311 Handle<JSFunction> constructor(
312 JSFunction::GlobalContextFromLiterals(*literals)->array_function());
313 Handle<Object> object = Factory::NewJSObject(constructor);
314
315 Handle<Object> copied_elements = Factory::CopyFixedArray(elements);
316
317 Handle<FixedArray> content = Handle<FixedArray>::cast(copied_elements);
318 for (int i = 0; i < content->length(); i++) {
319 if (content->get(i)->IsFixedArray()) {
320 // The value contains the constant_properties of a
321 // simple object literal.
322 Handle<FixedArray> fa(FixedArray::cast(content->get(i)));
323 Handle<Object> result =
324 CreateLiteralBoilerplate(literals, fa);
325 if (result.is_null()) return result;
326 content->set(i, *result);
327 }
328 }
329
330 // Set the elements.
331 Handle<JSArray>::cast(object)->SetContent(*content);
332 return object;
333 }
334
335
336 static Handle<Object> CreateLiteralBoilerplate(
337 Handle<FixedArray> literals,
338 Handle<FixedArray> array) {
339 Handle<FixedArray> elements = CompileTimeValue::GetElements(array);
340 switch (CompileTimeValue::GetType(array)) {
341 case CompileTimeValue::OBJECT_LITERAL:
342 return CreateObjectLiteralBoilerplate(literals, elements);
343 case CompileTimeValue::ARRAY_LITERAL:
344 return CreateArrayLiteralBoilerplate(literals, elements);
345 default:
346 UNREACHABLE();
347 return Handle<Object>::null();
348 }
349 }
350
351
352 static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {
353 HandleScope scope;
354 ASSERT(args.length() == 3);
355 // Copy the arguments.
356 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
357 CONVERT_SMI_CHECKED(literals_index, args[1]);
358 CONVERT_ARG_CHECKED(FixedArray, constant_properties, 2);
359
360 Handle<Object> result =
361 CreateObjectLiteralBoilerplate(literals, constant_properties);
362
363 if (result.is_null()) return Failure::Exception();
364
365 // Update the functions literal and return the boilerplate.
366 literals->set(literals_index, *result);
367
368 return *result;
369 }
370
371
372 static Object* Runtime_CreateArrayLiteralBoilerplate(Arguments args) {
201 // Takes a FixedArray of elements containing the literal elements of 373 // Takes a FixedArray of elements containing the literal elements of
202 // the array literal and produces JSArray with those elements. 374 // the array literal and produces JSArray with those elements.
203 // Additionally takes the literals array of the surrounding function 375 // Additionally takes the literals array of the surrounding function
204 // which contains the context from which to get the Array function 376 // which contains the context from which to get the Array function
205 // to use for creating the array literal. 377 // to use for creating the array literal.
206 ASSERT(args.length() == 2); 378 HandleScope scope;
207 CONVERT_CHECKED(FixedArray, elements, args[0]); 379 ASSERT(args.length() == 3);
208 CONVERT_CHECKED(FixedArray, literals, args[1]); 380 CONVERT_ARG_CHECKED(FixedArray, literals, 0);
209 JSFunction* constructor = 381 CONVERT_SMI_CHECKED(literals_index, args[1]);
210 JSFunction::GlobalContextFromLiterals(literals)->array_function(); 382 CONVERT_ARG_CHECKED(FixedArray, elements, 2);
211 // Create the JSArray.
212 Object* object = Heap::AllocateJSObject(constructor);
213 if (object->IsFailure()) return object;
214 383
215 // Copy the elements. 384 Handle<Object> object = CreateArrayLiteralBoilerplate(literals, elements);
216 Object* content = elements->Copy(); 385 if (object.is_null()) return Failure::Exception();
217 if (content->IsFailure()) return content;
218 386
219 // Set the elements. 387 // Update the functions literal and return the boilerplate.
220 JSArray::cast(object)->SetContent(FixedArray::cast(content)); 388 literals->set(literals_index, *object);
221 return object; 389 return *object;
222 } 390 }
223 391
224 392
225 static Object* Runtime_CreateCatchExtensionObject(Arguments args) { 393 static Object* Runtime_CreateCatchExtensionObject(Arguments args) {
226 ASSERT(args.length() == 2); 394 ASSERT(args.length() == 2);
227 CONVERT_CHECKED(String, key, args[0]); 395 CONVERT_CHECKED(String, key, args[0]);
228 Object* value = args[1]; 396 Object* value = args[1];
229 // Create a catch context extension object. 397 // Create a catch context extension object.
230 JSFunction* constructor = 398 JSFunction* constructor =
231 Top::context()->global_context()->context_extension_function(); 399 Top::context()->global_context()->context_extension_function();
(...skipping 6495 matching lines...) Expand 10 before | Expand all | Expand 10 after
6727 } else { 6895 } else {
6728 // Handle last resort GC and make sure to allow future allocations 6896 // Handle last resort GC and make sure to allow future allocations
6729 // to grow the heap without causing GCs (if possible). 6897 // to grow the heap without causing GCs (if possible).
6730 Counters::gc_last_resort_from_js.Increment(); 6898 Counters::gc_last_resort_from_js.Increment();
6731 Heap::CollectAllGarbage(); 6899 Heap::CollectAllGarbage();
6732 } 6900 }
6733 } 6901 }
6734 6902
6735 6903
6736 } } // namespace v8::internal 6904 } } // namespace v8::internal
OLDNEW
« src/objects.h ('K') | « src/runtime.h ('k') | test/mjsunit/fuzz-natives.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698