LCOV - code coverage report
Current view: top level - src/builtins - builtins-intl-gen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 46 46 100.0 %
Date: 2017-10-20 Functions: 5 5 100.0 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_INTL_SUPPORT
       6             : #error Internationalization is expected to be enabled.
       7             : #endif  // V8_INTL_SUPPORT
       8             : 
       9             : #include "src/builtins/builtins-utils-gen.h"
      10             : #include "src/code-stub-assembler.h"
      11             : #include "src/zone/zone-list-inl.h"  // TODO(mstarzinger): Temporary cycle breaker.
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16             : class IntlBuiltinsAssembler : public CodeStubAssembler {
      17             :  public:
      18             :   explicit IntlBuiltinsAssembler(compiler::CodeAssemblerState* state)
      19          62 :       : CodeStubAssembler(state) {}
      20             : };
      21             : 
      22         124 : TF_BUILTIN(StringToLowerCaseIntl, IntlBuiltinsAssembler) {
      23             :   Node* const string = Parameter(Descriptor::kString);
      24             :   Node* const context = Parameter(Descriptor::kContext);
      25             : 
      26             :   CSA_ASSERT(this, IsString(string));
      27             : 
      28          31 :   Label call_c(this), return_string(this), runtime(this, Label::kDeferred);
      29             : 
      30             :   // Early exit on empty strings.
      31          93 :   Node* const length = SmiUntag(LoadStringLength(string));
      32          93 :   GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_string);
      33             : 
      34             :   // Unpack strings if possible, and bail to runtime unless we get a one-byte
      35             :   // flat string.
      36             :   ToDirectStringAssembler to_direct(
      37          62 :       state(), string, ToDirectStringAssembler::kDontUnpackSlicedStrings);
      38          31 :   to_direct.TryToDirect(&runtime);
      39             : 
      40             :   Node* const instance_type = to_direct.instance_type();
      41             :   CSA_ASSERT(this,
      42             :              Word32BinaryNot(IsIndirectStringInstanceType(instance_type)));
      43          62 :   GotoIfNot(IsOneByteStringInstanceType(instance_type), &runtime);
      44             : 
      45             :   // For short strings, do the conversion in CSA through the lookup table.
      46             : 
      47          31 :   Node* const dst = AllocateSeqOneByteString(context, length);
      48             : 
      49             :   const int kMaxShortStringLength = 24;  // Determined empirically.
      50          62 :   GotoIf(IntPtrGreaterThan(length, IntPtrConstant(kMaxShortStringLength)),
      51          62 :          &call_c);
      52             : 
      53             :   {
      54          31 :     Node* const dst_ptr = PointerToSeqStringData(dst);
      55          62 :     VARIABLE(var_cursor, MachineType::PointerRepresentation(),
      56             :              IntPtrConstant(0));
      57             : 
      58             :     Node* const start_address = to_direct.PointerToData(&call_c);
      59          62 :     Node* const end_address = IntPtrAdd(start_address, length);
      60             : 
      61             :     Node* const to_lower_table_addr = ExternalConstant(
      62          62 :         ExternalReference::intl_to_latin1_lower_table(isolate()));
      63             : 
      64          93 :     VARIABLE(var_did_change, MachineRepresentation::kWord32, Int32Constant(0));
      65             : 
      66          31 :     VariableList push_vars({&var_cursor, &var_did_change}, zone());
      67             :     BuildFastLoop(push_vars, start_address, end_address,
      68          31 :                   [=, &var_cursor, &var_did_change](Node* current) {
      69          31 :                     Node* c = Load(MachineType::Uint8(), current);
      70             :                     Node* lower =
      71             :                         Load(MachineType::Uint8(), to_lower_table_addr,
      72          62 :                              ChangeInt32ToIntPtr(c));
      73             :                     StoreNoWriteBarrier(MachineRepresentation::kWord8, dst_ptr,
      74          31 :                                         var_cursor.value(), lower);
      75             : 
      76          62 :                     var_did_change.Bind(Word32Or(Word32NotEqual(c, lower),
      77         155 :                                                  var_did_change.value()));
      78             : 
      79          31 :                     Increment(&var_cursor);
      80          31 :                   },
      81          62 :                   kCharSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost);
      82             : 
      83             :     // Return the original string if it remained unchanged in order to preserve
      84             :     // e.g. internalization and private symbols (such as the preserved object
      85             :     // hash) on the source string.
      86          62 :     GotoIfNot(var_did_change.value(), &return_string);
      87             : 
      88          62 :     Return(dst);
      89             :   }
      90             : 
      91             :   // Call into C for case conversion. The signature is:
      92             :   // Object* ConvertOneByteToLower(String* src, String* dst, Isolate* isolate);
      93          31 :   BIND(&call_c);
      94             :   {
      95             :     Node* const src = to_direct.string();
      96             : 
      97             :     Node* const function_addr = ExternalConstant(
      98          62 :         ExternalReference::intl_convert_one_byte_to_lower(isolate()));
      99             :     Node* const isolate_ptr =
     100          62 :         ExternalConstant(ExternalReference::isolate_address(isolate()));
     101             : 
     102          31 :     MachineType type_ptr = MachineType::Pointer();
     103          31 :     MachineType type_tagged = MachineType::AnyTagged();
     104             : 
     105             :     Node* const result =
     106             :         CallCFunction3(type_tagged, type_tagged, type_tagged, type_ptr,
     107          31 :                        function_addr, src, dst, isolate_ptr);
     108             : 
     109          31 :     Return(result);
     110             :   }
     111             : 
     112          31 :   BIND(&return_string);
     113          31 :   Return(string);
     114             : 
     115          31 :   BIND(&runtime);
     116             :   {
     117             :     Node* const result = CallRuntime(Runtime::kStringToLowerCaseIntl,
     118          31 :                                      NoContextConstant(), string);
     119          31 :     Return(result);
     120          31 :   }
     121          31 : }
     122             : 
     123         124 : TF_BUILTIN(StringPrototypeToLowerCaseIntl, IntlBuiltinsAssembler) {
     124             :   Node* const maybe_string = Parameter(Descriptor::kReceiver);
     125             :   Node* const context = Parameter(Descriptor::kContext);
     126             : 
     127             :   Node* const string =
     128          31 :       ToThisString(context, maybe_string, "String.prototype.toLowerCase");
     129             : 
     130          62 :   Return(CallBuiltin(Builtins::kStringToLowerCaseIntl, context, string));
     131          31 : }
     132             : 
     133             : }  // namespace internal
     134             : }  // namespace v8

Generated by: LCOV version 1.10