OLD | NEW |
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 |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 table.Lookup(literal, hash, false, allocator) != NULL) { | 249 table.Lookup(literal, hash, false, allocator) != NULL) { |
250 property->set_emit_store(false); | 250 property->set_emit_store(false); |
251 } else { | 251 } else { |
252 // Add key to the table. | 252 // Add key to the table. |
253 table.Lookup(literal, hash, true, allocator); | 253 table.Lookup(literal, hash, true, allocator); |
254 } | 254 } |
255 } | 255 } |
256 } | 256 } |
257 | 257 |
258 | 258 |
| 259 bool ObjectLiteral::IsBoilerplateProperty(ObjectLiteral::Property* property) { |
| 260 return property != NULL && |
| 261 property->kind() != ObjectLiteral::Property::PROTOTYPE; |
| 262 } |
| 263 |
| 264 |
| 265 void ObjectLiteral::BuildConstantProperties(Isolate* isolate, int* depth) { |
| 266 if (!constant_properties_.is_null()) return; |
| 267 |
| 268 // Allocate a fixed array to hold all the constant properties. |
| 269 Handle<FixedArray> constant_properties = isolate->factory()->NewFixedArray( |
| 270 boilerplate_properties_ * 2, TENURED); |
| 271 |
| 272 int position = 0; |
| 273 // Accumulate the value in local variables and store it at the end. |
| 274 bool is_simple = true; |
| 275 int depth_acc = 1; |
| 276 uint32_t max_element_index = 0; |
| 277 uint32_t elements = 0; |
| 278 for (int i = 0; i < properties()->length(); i++) { |
| 279 ObjectLiteral::Property* property = properties()->at(i); |
| 280 if (!IsBoilerplateProperty(property)) { |
| 281 is_simple = false; |
| 282 continue; |
| 283 } |
| 284 MaterializedLiteral* m_literal = property->value()->AsMaterializedLiteral(); |
| 285 if (m_literal != NULL) { |
| 286 int inner_depth = 1; |
| 287 m_literal->BuildConstants(isolate, &inner_depth); |
| 288 if (inner_depth >= depth_acc) depth_acc = inner_depth + 1; |
| 289 } |
| 290 |
| 291 // Add CONSTANT and COMPUTED properties to boilerplate. Use undefined |
| 292 // value for COMPUTED properties, the real value is filled in at |
| 293 // runtime. The enumeration order is maintained. |
| 294 Handle<Object> key = property->key()->value(); |
| 295 Handle<Object> value = GetBoilerplateValue(property->value(), isolate); |
| 296 |
| 297 // Ensure objects that may, at any point in time, contain fields with double |
| 298 // representation are always treated as nested objects. This is true for |
| 299 // computed fields (value is undefined), and smi and double literals |
| 300 // (value->IsNumber()). |
| 301 // TODO(verwaest): Remove once we can store them inline. |
| 302 if (FLAG_track_double_fields && |
| 303 (value->IsNumber() || value->IsUninitialized())) { |
| 304 may_store_doubles_ = true; |
| 305 } |
| 306 |
| 307 is_simple = is_simple && !value->IsUninitialized(); |
| 308 |
| 309 // Keep track of the number of elements in the object literal and |
| 310 // the largest element index. If the largest element index is |
| 311 // much larger than the number of elements, creating an object |
| 312 // literal with fast elements will be a waste of space. |
| 313 uint32_t element_index = 0; |
| 314 if (key->IsString() |
| 315 && Handle<String>::cast(key)->AsArrayIndex(&element_index) |
| 316 && element_index > max_element_index) { |
| 317 max_element_index = element_index; |
| 318 elements++; |
| 319 } else if (key->IsSmi()) { |
| 320 int key_value = Smi::cast(*key)->value(); |
| 321 if (key_value > 0 |
| 322 && static_cast<uint32_t>(key_value) > max_element_index) { |
| 323 max_element_index = key_value; |
| 324 } |
| 325 elements++; |
| 326 } |
| 327 |
| 328 // Add name, value pair to the fixed array. |
| 329 constant_properties->set(position++, *key); |
| 330 constant_properties->set(position++, *value); |
| 331 } |
| 332 |
| 333 constant_properties_ = constant_properties; |
| 334 fast_elements_ = |
| 335 (max_element_index <= 32) || ((2 * elements) >= max_element_index); |
| 336 set_is_simple(is_simple); |
| 337 if (depth != NULL) *depth = depth_acc; |
| 338 } |
| 339 |
| 340 |
| 341 void ArrayLiteral::BuildConstantElements(Isolate* isolate, int* depth) { |
| 342 if (!constant_elements_.is_null()) return; |
| 343 |
| 344 // Allocate a fixed array to hold all the object literals. |
| 345 Handle<JSArray> array = |
| 346 isolate->factory()->NewJSArray(0, FAST_HOLEY_SMI_ELEMENTS); |
| 347 isolate->factory()->SetElementsCapacityAndLength( |
| 348 array, values()->length(), values()->length()); |
| 349 |
| 350 // Fill in the literals. |
| 351 bool is_simple = true; |
| 352 int depth_acc = 1; |
| 353 bool is_holey = false; |
| 354 for (int i = 0, n = values()->length(); i < n; i++) { |
| 355 Expression* element = values()->at(i); |
| 356 MaterializedLiteral* m_literal = element->AsMaterializedLiteral(); |
| 357 if (m_literal != NULL) { |
| 358 int inner_depth = 1; |
| 359 m_literal->BuildConstants(isolate, &inner_depth); |
| 360 if (inner_depth + 1 > depth_acc) depth_acc = inner_depth + 1; |
| 361 } |
| 362 Handle<Object> boilerplate_value = GetBoilerplateValue(element, isolate); |
| 363 if (boilerplate_value->IsTheHole()) { |
| 364 is_holey = true; |
| 365 } else if (boilerplate_value->IsUninitialized()) { |
| 366 is_simple = false; |
| 367 JSObject::SetOwnElement( |
| 368 array, i, handle(Smi::FromInt(0), isolate), kNonStrictMode); |
| 369 } else { |
| 370 JSObject::SetOwnElement(array, i, boilerplate_value, kNonStrictMode); |
| 371 } |
| 372 } |
| 373 |
| 374 Handle<FixedArrayBase> element_values(array->elements()); |
| 375 |
| 376 // Simple and shallow arrays can be lazily copied, we transform the |
| 377 // elements array to a copy-on-write array. |
| 378 if (is_simple && depth_acc == 1 && values()->length() > 0 && |
| 379 array->HasFastSmiOrObjectElements()) { |
| 380 element_values->set_map(isolate->heap()->fixed_cow_array_map()); |
| 381 } |
| 382 |
| 383 // Remember both the literal's constant values as well as the ElementsKind |
| 384 // in a 2-element FixedArray. |
| 385 Handle<FixedArray> literals = isolate->factory()->NewFixedArray(2, TENURED); |
| 386 |
| 387 ElementsKind kind = array->GetElementsKind(); |
| 388 kind = is_holey ? GetHoleyElementsKind(kind) : GetPackedElementsKind(kind); |
| 389 |
| 390 literals->set(0, Smi::FromInt(kind)); |
| 391 literals->set(1, *element_values); |
| 392 |
| 393 constant_elements_ = literals; |
| 394 set_is_simple(is_simple); |
| 395 if (depth != NULL) *depth = depth_acc; |
| 396 } |
| 397 |
| 398 |
| 399 Handle<Object> MaterializedLiteral::GetBoilerplateValue(Expression* expression, |
| 400 Isolate* isolate) { |
| 401 if (expression->AsLiteral() != NULL) { |
| 402 return expression->AsLiteral()->value(); |
| 403 } |
| 404 if (CompileTimeValue::IsCompileTimeValue(expression)) { |
| 405 return CompileTimeValue::GetValue(isolate, expression); |
| 406 } |
| 407 return isolate->factory()->uninitialized_value(); |
| 408 } |
| 409 |
| 410 |
| 411 void MaterializedLiteral::BuildConstants(Isolate* isolate, int* depth) { |
| 412 if (IsArrayLiteral()) { |
| 413 return AsArrayLiteral()->BuildConstantElements(isolate, depth); |
| 414 } |
| 415 if (IsObjectLiteral()) { |
| 416 return AsObjectLiteral()->BuildConstantProperties(isolate, depth); |
| 417 } |
| 418 ASSERT(IsRegExpLiteral()); |
| 419 } |
| 420 |
| 421 |
259 void TargetCollector::AddTarget(Label* target, Zone* zone) { | 422 void TargetCollector::AddTarget(Label* target, Zone* zone) { |
260 // Add the label to the collector, but discard duplicates. | 423 // Add the label to the collector, but discard duplicates. |
261 int length = targets_.length(); | 424 int length = targets_.length(); |
262 for (int i = 0; i < length; i++) { | 425 for (int i = 0; i < length; i++) { |
263 if (targets_[i] == target) return; | 426 if (targets_[i] == target) return; |
264 } | 427 } |
265 targets_.Add(target, zone); | 428 targets_.Add(target, zone); |
266 } | 429 } |
267 | 430 |
268 | 431 |
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1163 OS::SNPrintF(buffer, "%d", Smi::cast(*value_)->value()); | 1326 OS::SNPrintF(buffer, "%d", Smi::cast(*value_)->value()); |
1164 str = arr; | 1327 str = arr; |
1165 } else { | 1328 } else { |
1166 str = DoubleToCString(value_->Number(), buffer); | 1329 str = DoubleToCString(value_->Number(), buffer); |
1167 } | 1330 } |
1168 return isolate_->factory()->NewStringFromAscii(CStrVector(str)); | 1331 return isolate_->factory()->NewStringFromAscii(CStrVector(str)); |
1169 } | 1332 } |
1170 | 1333 |
1171 | 1334 |
1172 } } // namespace v8::internal | 1335 } } // namespace v8::internal |
OLD | NEW |