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

Side by Side Diff: src/runtime.cc

Issue 8733: Merged bleeding_edge r599:645 into regexp2000. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/regexp2000/
Patch Set: Created 12 years, 1 month 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
« no previous file with comments | « src/runtime.h ('k') | src/runtime.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 ASSERT(args.length() == 1); 313 ASSERT(args.length() == 1);
314 Object* arg = args[0]; 314 Object* arg = args[0];
315 bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo(); 315 bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();
316 return Heap::ToBoolean(result); 316 return Heap::ToBoolean(result);
317 } 317 }
318 318
319 319
320 static Object* Runtime_GetTemplateField(Arguments args) { 320 static Object* Runtime_GetTemplateField(Arguments args) {
321 ASSERT(args.length() == 2); 321 ASSERT(args.length() == 2);
322 CONVERT_CHECKED(HeapObject, templ, args[0]); 322 CONVERT_CHECKED(HeapObject, templ, args[0]);
323 RUNTIME_ASSERT(templ->IsStruct());
324 CONVERT_CHECKED(Smi, field, args[1]); 323 CONVERT_CHECKED(Smi, field, args[1]);
325 return HeapObject::GetHeapObjectField(templ, field->value()); 324 int index = field->value();
325 int offset = index * kPointerSize + HeapObject::kHeaderSize;
326 InstanceType type = templ->map()->instance_type();
327 RUNTIME_ASSERT(type == FUNCTION_TEMPLATE_INFO_TYPE ||
328 type == OBJECT_TEMPLATE_INFO_TYPE);
329 RUNTIME_ASSERT(offset > 0);
330 if (type == FUNCTION_TEMPLATE_INFO_TYPE) {
331 RUNTIME_ASSERT(offset < FunctionTemplateInfo::kSize);
332 } else {
333 RUNTIME_ASSERT(offset < ObjectTemplateInfo::kSize);
334 }
335 return *HeapObject::RawField(templ, offset);
326 } 336 }
327 337
328 338
329 static Object* ThrowRedeclarationError(const char* type, Handle<String> name) { 339 static Object* ThrowRedeclarationError(const char* type, Handle<String> name) {
330 HandleScope scope; 340 HandleScope scope;
331 Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type)); 341 Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));
332 Handle<Object> args[2] = { type_handle, name }; 342 Handle<Object> args[2] = { type_handle, name };
333 Handle<Object> error = 343 Handle<Object> error =
334 Factory::NewTypeError("redeclaration", HandleVector(args, 2)); 344 Factory::NewTypeError("redeclaration", HandleVector(args, 2));
335 return Top::Throw(*error); 345 return Top::Throw(*error);
(...skipping 3644 matching lines...) Expand 10 before | Expand all | Expand 10 after
3980 FixedArray* elements = FixedArray::cast(array->elements()); 3990 FixedArray* elements = FixedArray::cast(array->elements());
3981 for (int i = 0; i < length; i++) { 3991 for (int i = 0; i < length; i++) {
3982 if (elements->get(i) == element) return Heap::false_value(); 3992 if (elements->get(i) == element) return Heap::false_value();
3983 } 3993 }
3984 Object* obj = array->SetFastElement(length, element); 3994 Object* obj = array->SetFastElement(length, element);
3985 if (obj->IsFailure()) return obj; 3995 if (obj->IsFailure()) return obj;
3986 return Heap::true_value(); 3996 return Heap::true_value();
3987 } 3997 }
3988 3998
3989 3999
4000 /**
4001 * A simple visitor visits every element of Array's.
4002 * The backend storage can be a fixed array for fast elements case,
4003 * or a dictionary for sparse array. Since Dictionary is a subtype
4004 * of FixedArray, the class can be used by both fast and slow cases.
4005 * The second parameter of the constructor, fast_elements, specifies
4006 * whether the storage is a FixedArray or Dictionary.
4007 *
4008 * An index limit is used to deal with the situation that a result array
4009 * length overflows 32-bit non-negative integer.
4010 */
4011 class ArrayConcatVisitor {
4012 public:
4013 ArrayConcatVisitor(Handle<FixedArray> storage,
4014 uint32_t index_limit,
4015 bool fast_elements) :
4016 storage_(storage), index_limit_(index_limit),
4017 fast_elements_(fast_elements), index_offset_(0) { }
4018
4019 void visit(uint32_t i, Handle<Object> elm) {
4020 uint32_t index = i + index_offset_;
4021 if (index >= index_limit_) return;
4022
4023 if (fast_elements_) {
4024 ASSERT(index < static_cast<uint32_t>(storage_->length()));
4025 storage_->set(index, *elm);
4026
4027 } else {
4028 Handle<Dictionary> dict = Handle<Dictionary>::cast(storage_);
4029 Handle<Dictionary> result =
4030 Factory::DictionaryAtNumberPut(dict, index, elm);
4031 if (!result.is_identical_to(dict))
4032 storage_ = result;
4033 }
4034 }
4035
4036 void increase_index_offset(uint32_t delta) {
4037 index_offset_ += delta;
4038 }
4039
4040 private:
4041 Handle<FixedArray> storage_;
4042 uint32_t index_limit_;
4043 bool fast_elements_;
4044 uint32_t index_offset_;
4045 };
4046
4047
4048 /**
4049 * A helper function that visits elements of a JSObject. Only elements
4050 * whose index between 0 and range (exclusive) are visited.
4051 *
4052 * If the third parameter, visitor, is not NULL, the visitor is called
4053 * with parameters, 'visitor_index_offset + element index' and the element.
4054 *
4055 * It returns the number of visisted elements.
4056 */
4057 static uint32_t IterateElements(Handle<JSObject> receiver,
4058 uint32_t range,
4059 ArrayConcatVisitor* visitor) {
4060 uint32_t num_of_elements = 0;
4061
4062 if (receiver->HasFastElements()) {
4063 Handle<FixedArray> elements(FixedArray::cast(receiver->elements()));
4064 uint32_t len = elements->length();
4065 if (range < len) len = range;
4066
4067 for (uint32_t j = 0; j < len; j++) {
4068 Handle<Object> e(elements->get(j));
4069 if (!e->IsTheHole()) {
4070 num_of_elements++;
4071 if (visitor)
4072 visitor->visit(j, e);
4073 }
4074 }
4075
4076 } else {
4077 Handle<Dictionary> dict(receiver->element_dictionary());
4078 uint32_t capacity = dict->Capacity();
4079 for (uint32_t j = 0; j < capacity; j++) {
4080 Handle<Object> k(dict->KeyAt(j));
4081 if (dict->IsKey(*k)) {
4082 ASSERT(k->IsNumber());
4083 uint32_t index = static_cast<uint32_t>(k->Number());
4084 if (index < range) {
4085 num_of_elements++;
4086 if (visitor) {
4087 visitor->visit(index,
4088 Handle<Object>(dict->ValueAt(j)));
4089 }
4090 }
4091 }
4092 }
4093 }
4094
4095 return num_of_elements;
4096 }
4097
4098
4099 /**
4100 * A helper function that visits elements of an Array object, and elements
4101 * on its prototypes.
4102 *
4103 * Elements on prototypes are visited first, and only elements whose indices
4104 * less than Array length are visited.
4105 *
4106 * If a ArrayConcatVisitor object is given, the visitor is called with
4107 * parameters, element's index + visitor_index_offset and the element.
4108 */
4109 static uint32_t IterateArrayAndPrototypeElements(Handle<JSArray> array,
4110 ArrayConcatVisitor* visitor) {
4111 uint32_t range = static_cast<uint32_t>(array->length()->Number());
4112 Handle<Object> obj = array;
4113
4114 static const int kEstimatedPrototypes = 3;
4115 List< Handle<JSObject> > objects(kEstimatedPrototypes);
4116
4117 // Visit prototype first. If an element on the prototype is shadowed by
4118 // the inheritor using the same index, the ArrayConcatVisitor visits
4119 // the prototype element before the shadowing element.
4120 // The visitor can simply overwrite the old value by new value using
4121 // the same index. This follows Array::concat semantics.
4122 while (!obj->IsNull()) {
4123 objects.Add(Handle<JSObject>::cast(obj));
4124 obj = Handle<Object>(obj->GetPrototype());
4125 }
4126
4127 uint32_t nof_elements = 0;
4128 for (int i = objects.length() - 1; i >= 0; i--) {
4129 Handle<JSObject> obj = objects[i];
4130 nof_elements +=
4131 IterateElements(Handle<JSObject>::cast(obj), range, visitor);
4132 }
4133
4134 return nof_elements;
4135 }
4136
4137
4138 /**
4139 * A helper function of Runtime_ArrayConcat.
4140 *
4141 * The first argument is an Array of arrays and objects. It is the
4142 * same as the arguments array of Array::concat JS function.
4143 *
4144 * If an argument is an Array object, the function visits array
4145 * elements. If an argument is not an Array object, the function
4146 * visits the object as if it is an one-element array.
4147 *
4148 * If the result array index overflows 32-bit integer, the rounded
4149 * non-negative number is used as new length. For example, if one
4150 * array length is 2^32 - 1, second array length is 1, the
4151 * concatenated array length is 0.
4152 */
4153 static uint32_t IterateArguments(Handle<JSArray> arguments,
4154 ArrayConcatVisitor* visitor) {
4155 uint32_t visited_elements = 0;
4156 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
4157
4158 for (uint32_t i = 0; i < num_of_args; i++) {
4159 Handle<Object> obj(arguments->GetElement(i));
4160 if (obj->IsJSArray()) {
4161 Handle<JSArray> array = Handle<JSArray>::cast(obj);
4162 uint32_t len = static_cast<uint32_t>(array->length()->Number());
4163 uint32_t nof_elements =
4164 IterateArrayAndPrototypeElements(array, visitor);
4165 // Total elements of array and its prototype chain can be more than
4166 // the array length, but ArrayConcat can only concatenate at most
4167 // the array length number of elements.
4168 visited_elements += (nof_elements > len) ? len : nof_elements;
4169 if (visitor) visitor->increase_index_offset(len);
4170
4171 } else {
4172 if (visitor) {
4173 visitor->visit(0, obj);
4174 visitor->increase_index_offset(1);
4175 }
4176 visited_elements++;
4177 }
4178 }
4179 return visited_elements;
4180 }
4181
4182
4183 /**
4184 * Array::concat implementation.
4185 * See ECMAScript 262, 15.4.4.4.
4186 */
4187 static Object* Runtime_ArrayConcat(Arguments args) {
4188 ASSERT(args.length() == 1);
4189 HandleScope handle_scope;
4190
4191 CONVERT_CHECKED(JSArray, arg_arrays, args[0]);
4192 Handle<JSArray> arguments(arg_arrays);
4193
4194 // Pass 1: estimate the number of elements of the result
4195 // (it could be more than real numbers if prototype has elements).
4196 uint32_t result_length = 0;
4197 uint32_t num_of_args = static_cast<uint32_t>(arguments->length()->Number());
4198
4199 { AssertNoAllocation nogc;
4200 for (uint32_t i = 0; i < num_of_args; i++) {
4201 Object* obj = arguments->GetElement(i);
4202 if (obj->IsJSArray()) {
4203 result_length +=
4204 static_cast<uint32_t>(JSArray::cast(obj)->length()->Number());
4205 } else {
4206 result_length++;
4207 }
4208 }
4209 }
4210
4211 // Allocate an empty array, will set length and content later.
4212 Handle<JSArray> result = Factory::NewJSArray(0);
4213
4214 uint32_t estimate_nof_elements = IterateArguments(arguments, NULL);
4215 // If estimated number of elements is more than half of length, a
4216 // fixed array (fast case) is more time and space-efficient than a
4217 // dictionary.
4218 bool fast_case = (estimate_nof_elements * 2) >= result_length;
4219
4220 Handle<FixedArray> storage;
4221 if (fast_case) {
4222 // The backing storage array must have non-existing elements to
4223 // preserve holes across concat operations.
4224 storage = Factory::NewFixedArrayWithHoles(result_length);
4225
4226 } else {
4227 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
4228 uint32_t at_least_space_for = estimate_nof_elements +
4229 (estimate_nof_elements >> 2);
4230 storage = Handle<FixedArray>::cast(
4231 Factory::NewDictionary(at_least_space_for));
4232 }
4233
4234 Handle<Object> len = Factory::NewNumber(static_cast<double>(result_length));
4235
4236 ArrayConcatVisitor visitor(storage, result_length, fast_case);
4237
4238 IterateArguments(arguments, &visitor);
4239
4240 result->set_length(*len);
4241 result->set_elements(*storage);
4242
4243 return *result;
4244 }
4245
4246
3990 // This will not allocate (flatten the string), but it may run 4247 // This will not allocate (flatten the string), but it may run
3991 // very slowly for very deeply nested ConsStrings. For debugging use only. 4248 // very slowly for very deeply nested ConsStrings. For debugging use only.
3992 static Object* Runtime_GlobalPrint(Arguments args) { 4249 static Object* Runtime_GlobalPrint(Arguments args) {
3993 NoHandleAllocation ha; 4250 NoHandleAllocation ha;
3994 ASSERT(args.length() == 1); 4251 ASSERT(args.length() == 1);
3995 4252
3996 CONVERT_CHECKED(String, string, args[0]); 4253 CONVERT_CHECKED(String, string, args[0]);
3997 StringInputBuffer buffer(string); 4254 StringInputBuffer buffer(string);
3998 while (buffer.has_more()) { 4255 while (buffer.has_more()) {
3999 uint16_t character = buffer.GetNext(); 4256 uint16_t character = buffer.GetNext();
(...skipping 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after
5516 if (strcmp(f->name, name) == 0) { 5773 if (strcmp(f->name, name) == 0) {
5517 return f; 5774 return f;
5518 } 5775 }
5519 } 5776 }
5520 return NULL; 5777 return NULL;
5521 } 5778 }
5522 5779
5523 5780
5524 void Runtime::PerformGC(Object* result) { 5781 void Runtime::PerformGC(Object* result) {
5525 Failure* failure = Failure::cast(result); 5782 Failure* failure = Failure::cast(result);
5526 // Try to do a garbage collection; ignore it if it fails. The C 5783 if (failure->IsRetryAfterGC()) {
5527 // entry stub will throw an out-of-memory exception in that case. 5784 // Try to do a garbage collection; ignore it if it fails. The C
5528 Heap::CollectGarbage(failure->requested(), failure->allocation_space()); 5785 // entry stub will throw an out-of-memory exception in that case.
5786 Heap::CollectGarbage(failure->requested(), failure->allocation_space());
5787 } else {
5788 // Handle last resort GC and make sure to allow future allocations
5789 // to grow the heap without causing GCs (if possible).
5790 Heap::CollectAllGarbage();
5791 }
5529 } 5792 }
5530 5793
5531 5794
5532 } } // namespace v8::internal 5795 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | src/runtime.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698