OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/code-stubs.h" | 5 #include "src/code-stubs.h" |
6 | 6 |
7 #include "src/bailout-reason.h" | 7 #include "src/bailout-reason.h" |
8 #include "src/field-index.h" | 8 #include "src/field-index.h" |
9 #include "src/hydrogen.h" | 9 #include "src/hydrogen.h" |
10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 HValue* code_object, HValue* literals); | 106 HValue* code_object, HValue* literals); |
107 void BuildInstallCode(HValue* js_function, HValue* shared_info); | 107 void BuildInstallCode(HValue* js_function, HValue* shared_info); |
108 | 108 |
109 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, | 109 HInstruction* LoadFromOptimizedCodeMap(HValue* optimized_map, |
110 HValue* iterator, | 110 HValue* iterator, |
111 int field_offset); | 111 int field_offset); |
112 void BuildInstallFromOptimizedCodeMap(HValue* js_function, | 112 void BuildInstallFromOptimizedCodeMap(HValue* js_function, |
113 HValue* shared_info, | 113 HValue* shared_info, |
114 HValue* native_context); | 114 HValue* native_context); |
115 | 115 |
116 HValue* CheckString(HValue* input, bool convert); | 116 HValue* BuildToString(HValue* input, bool convert); |
| 117 HValue* BuildToPrimitive(HValue* input, HValue* input_map); |
117 | 118 |
118 private: | 119 private: |
119 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); | 120 HValue* BuildArraySingleArgumentConstructor(JSArrayBuilder* builder); |
120 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, | 121 HValue* BuildArrayNArgumentsConstructor(JSArrayBuilder* builder, |
121 ElementsKind kind); | 122 ElementsKind kind); |
122 | 123 |
123 base::SmartArrayPointer<HParameter*> parameters_; | 124 base::SmartArrayPointer<HParameter*> parameters_; |
124 HValue* arguments_length_; | 125 HValue* arguments_length_; |
125 CompilationInfo* info_; | 126 CompilationInfo* info_; |
126 CodeStubDescriptor descriptor_; | 127 CodeStubDescriptor descriptor_; |
(...skipping 1324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1451 result_type, state.fixed_right_arg(), | 1452 result_type, state.fixed_right_arg(), |
1452 allocation_mode, state.strength()); | 1453 allocation_mode, state.strength()); |
1453 } | 1454 } |
1454 | 1455 |
1455 | 1456 |
1456 Handle<Code> BinaryOpWithAllocationSiteStub::GenerateCode() { | 1457 Handle<Code> BinaryOpWithAllocationSiteStub::GenerateCode() { |
1457 return DoGenerateCode(this); | 1458 return DoGenerateCode(this); |
1458 } | 1459 } |
1459 | 1460 |
1460 | 1461 |
1461 HValue* CodeStubGraphBuilderBase::CheckString(HValue* input, bool convert) { | 1462 HValue* CodeStubGraphBuilderBase::BuildToString(HValue* input, bool convert) { |
1462 if (!convert) return BuildCheckString(input); | 1463 if (!convert) return BuildCheckString(input); |
1463 IfBuilder if_inputissmi(this); | 1464 IfBuilder if_inputissmi(this); |
1464 HValue* inputissmi = if_inputissmi.If<HIsSmiAndBranch>(input); | 1465 HValue* inputissmi = if_inputissmi.If<HIsSmiAndBranch>(input); |
1465 if_inputissmi.Then(); | 1466 if_inputissmi.Then(); |
1466 { | 1467 { |
1467 // Convert the input smi to a string. | 1468 // Convert the input smi to a string. |
1468 Push(BuildNumberToString(input, Type::SignedSmall())); | 1469 Push(BuildNumberToString(input, Type::SignedSmall())); |
1469 } | 1470 } |
1470 if_inputissmi.Else(); | 1471 if_inputissmi.Else(); |
1471 { | 1472 { |
(...skipping 17 matching lines...) Expand all Loading... |
1489 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); | 1490 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); |
1490 if_inputisprimitive.If<HCompareNumericAndBranch>( | 1491 if_inputisprimitive.If<HCompareNumericAndBranch>( |
1491 input_instance_type, Add<HConstant>(LAST_PRIMITIVE_TYPE), Token::LTE); | 1492 input_instance_type, Add<HConstant>(LAST_PRIMITIVE_TYPE), Token::LTE); |
1492 if_inputisprimitive.Then(); | 1493 if_inputisprimitive.Then(); |
1493 { | 1494 { |
1494 // The input is already a primitive. | 1495 // The input is already a primitive. |
1495 Push(input); | 1496 Push(input); |
1496 } | 1497 } |
1497 if_inputisprimitive.Else(); | 1498 if_inputisprimitive.Else(); |
1498 { | 1499 { |
1499 // TODO(bmeurer): Add support for fast ToPrimitive conversion using | 1500 // Convert the input to a primitive. |
1500 // a dedicated ToPrimitiveStub. | 1501 Push(BuildToPrimitive(input, input_map)); |
1501 Add<HPushArguments>(input); | |
1502 Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToPrimitive), | |
1503 1)); | |
1504 } | 1502 } |
1505 if_inputisprimitive.End(); | 1503 if_inputisprimitive.End(); |
1506 // Convert the primitive to a string value. | 1504 // Convert the primitive to a string value. |
1507 ToStringDescriptor descriptor(isolate()); | 1505 ToStringDescriptor descriptor(isolate()); |
1508 ToStringStub stub(isolate()); | 1506 ToStringStub stub(isolate()); |
1509 HValue* values[] = {context(), Pop()}; | 1507 HValue* values[] = {context(), Pop()}; |
1510 Push(AddUncasted<HCallWithDescriptor>( | 1508 Push(AddUncasted<HCallWithDescriptor>( |
1511 Add<HConstant>(stub.GetCode()), 0, descriptor, | 1509 Add<HConstant>(stub.GetCode()), 0, descriptor, |
1512 Vector<HValue*>(values, arraysize(values)))); | 1510 Vector<HValue*>(values, arraysize(values)))); |
1513 } | 1511 } |
1514 if_inputisstring.End(); | 1512 if_inputisstring.End(); |
1515 } | 1513 } |
1516 if_inputissmi.End(); | 1514 if_inputissmi.End(); |
1517 return Pop(); | 1515 return Pop(); |
1518 } | 1516 } |
1519 | 1517 |
1520 | 1518 |
| 1519 HValue* CodeStubGraphBuilderBase::BuildToPrimitive(HValue* input, |
| 1520 HValue* input_map) { |
| 1521 // Get the native context of the caller. |
| 1522 HValue* native_context = BuildGetNativeContext(); |
| 1523 |
| 1524 // Determine the initial map of the %ObjectPrototype%. |
| 1525 HValue* object_function_prototype_map = |
| 1526 Add<HLoadNamedField>(native_context, nullptr, |
| 1527 HObjectAccess::ForContextSlot( |
| 1528 Context::OBJECT_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 1529 |
| 1530 // Determine the initial map of the %StringPrototype%. |
| 1531 HValue* string_function_prototype_map = |
| 1532 Add<HLoadNamedField>(native_context, nullptr, |
| 1533 HObjectAccess::ForContextSlot( |
| 1534 Context::STRING_FUNCTION_PROTOTYPE_MAP_INDEX)); |
| 1535 |
| 1536 // Determine the initial map of the String function. |
| 1537 HValue* string_function = Add<HLoadNamedField>( |
| 1538 native_context, nullptr, |
| 1539 HObjectAccess::ForContextSlot(Context::STRING_FUNCTION_INDEX)); |
| 1540 HValue* string_function_initial_map = Add<HLoadNamedField>( |
| 1541 string_function, nullptr, HObjectAccess::ForPrototypeOrInitialMap()); |
| 1542 |
| 1543 // Determine the map of the [[Prototype]] of {input}. |
| 1544 HValue* input_prototype = |
| 1545 Add<HLoadNamedField>(input_map, nullptr, HObjectAccess::ForPrototype()); |
| 1546 HValue* input_prototype_map = |
| 1547 Add<HLoadNamedField>(input_prototype, nullptr, HObjectAccess::ForMap()); |
| 1548 |
| 1549 // For string wrappers (JSValue instances with [[StringData]] internal |
| 1550 // fields), we can shortcirciut the ToPrimitive if |
| 1551 // |
| 1552 // (a) the {input} map matches the initial map of the String function, |
| 1553 // (b) the {input} [[Prototype]] is the unmodified %StringPrototype% (i.e. |
| 1554 // no one monkey-patched toString, @@toPrimitive or valueOf), and |
| 1555 // (c) the %ObjectPrototype% (i.e. the [[Prototype]] of the |
| 1556 // %StringPrototype%) is also unmodified, that is no one sneaked a |
| 1557 // @@toPrimitive into the %ObjectPrototype%. |
| 1558 // |
| 1559 // If all these assumptions hold, we can just take the [[StringData]] value |
| 1560 // and return it. |
| 1561 // TODO(bmeurer): This just repairs a regression introduced by removing the |
| 1562 // weird (and broken) intrinsic %_IsStringWrapperSafeForDefaultValue, which |
| 1563 // was intendend to something similar to this, although less efficient and |
| 1564 // wrong in the presence of @@toPrimitive. Long-term we might want to move |
| 1565 // into the direction of having a ToPrimitiveStub that can do common cases |
| 1566 // while staying in JavaScript land (i.e. not going to C++). |
| 1567 IfBuilder if_inputisstringwrapper(this); |
| 1568 if_inputisstringwrapper.If<HCompareObjectEqAndBranch>( |
| 1569 input_map, string_function_initial_map); |
| 1570 if_inputisstringwrapper.And(); |
| 1571 if_inputisstringwrapper.If<HCompareObjectEqAndBranch>( |
| 1572 input_prototype_map, string_function_prototype_map); |
| 1573 if_inputisstringwrapper.And(); |
| 1574 if_inputisstringwrapper.If<HCompareObjectEqAndBranch>( |
| 1575 Add<HLoadNamedField>(Add<HLoadNamedField>(input_prototype_map, nullptr, |
| 1576 HObjectAccess::ForPrototype()), |
| 1577 nullptr, HObjectAccess::ForMap()), |
| 1578 object_function_prototype_map); |
| 1579 if_inputisstringwrapper.Then(); |
| 1580 { |
| 1581 Push(BuildLoadNamedField( |
| 1582 input, FieldIndex::ForInObjectOffset(JSValue::kValueOffset))); |
| 1583 } |
| 1584 if_inputisstringwrapper.Else(); |
| 1585 { |
| 1586 // TODO(bmeurer): Add support for fast ToPrimitive conversion using |
| 1587 // a dedicated ToPrimitiveStub. |
| 1588 Add<HPushArguments>(input); |
| 1589 Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToPrimitive), 1)); |
| 1590 } |
| 1591 if_inputisstringwrapper.End(); |
| 1592 return Pop(); |
| 1593 } |
| 1594 |
| 1595 |
1521 template <> | 1596 template <> |
1522 HValue* CodeStubGraphBuilder<StringAddStub>::BuildCodeInitializedStub() { | 1597 HValue* CodeStubGraphBuilder<StringAddStub>::BuildCodeInitializedStub() { |
1523 StringAddStub* stub = casted_stub(); | 1598 StringAddStub* stub = casted_stub(); |
1524 StringAddFlags flags = stub->flags(); | 1599 StringAddFlags flags = stub->flags(); |
1525 PretenureFlag pretenure_flag = stub->pretenure_flag(); | 1600 PretenureFlag pretenure_flag = stub->pretenure_flag(); |
1526 | 1601 |
1527 HValue* left = GetParameter(StringAddStub::kLeft); | 1602 HValue* left = GetParameter(StringAddStub::kLeft); |
1528 HValue* right = GetParameter(StringAddStub::kRight); | 1603 HValue* right = GetParameter(StringAddStub::kRight); |
1529 | 1604 |
1530 // Make sure that both arguments are strings if not known in advance. | 1605 // Make sure that both arguments are strings if not known in advance. |
1531 if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { | 1606 if ((flags & STRING_ADD_CHECK_LEFT) == STRING_ADD_CHECK_LEFT) { |
1532 left = | 1607 left = |
1533 CheckString(left, (flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT); | 1608 BuildToString(left, (flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT); |
1534 } | 1609 } |
1535 if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { | 1610 if ((flags & STRING_ADD_CHECK_RIGHT) == STRING_ADD_CHECK_RIGHT) { |
1536 right = | 1611 right = BuildToString(right, |
1537 CheckString(right, (flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT); | 1612 (flags & STRING_ADD_CONVERT) == STRING_ADD_CONVERT); |
1538 } | 1613 } |
1539 | 1614 |
1540 return BuildStringAdd(left, right, HAllocationMode(pretenure_flag)); | 1615 return BuildStringAdd(left, right, HAllocationMode(pretenure_flag)); |
1541 } | 1616 } |
1542 | 1617 |
1543 | 1618 |
1544 Handle<Code> StringAddStub::GenerateCode() { | 1619 Handle<Code> StringAddStub::GenerateCode() { |
1545 return DoGenerateCode(this); | 1620 return DoGenerateCode(this); |
1546 } | 1621 } |
1547 | 1622 |
(...skipping 727 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2275 return Pop(); | 2350 return Pop(); |
2276 } | 2351 } |
2277 | 2352 |
2278 | 2353 |
2279 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2354 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2280 return DoGenerateCode(this); | 2355 return DoGenerateCode(this); |
2281 } | 2356 } |
2282 | 2357 |
2283 } // namespace internal | 2358 } // namespace internal |
2284 } // namespace v8 | 2359 } // namespace v8 |
OLD | NEW |