| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 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 | 
|  | 12 namespace v8 { | 
|  | 13 namespace internal { | 
|  | 14 | 
|  | 15 class IntlBuiltinsAssembler : public CodeStubAssembler { | 
|  | 16  public: | 
|  | 17   explicit IntlBuiltinsAssembler(compiler::CodeAssemblerState* state) | 
|  | 18       : CodeStubAssembler(state) {} | 
|  | 19 | 
|  | 20  protected: | 
|  | 21   Node* IsUpperOrNonAscii(Node* const c) { | 
|  | 22     Label out(this), return_true(this); | 
|  | 23     VARIABLE(var_result, MachineRepresentation::kWord32, Int32Constant(0)); | 
|  | 24 | 
|  | 25     Node* const non_ascii_mask = Int32Constant(~0x7F); | 
|  | 26     GotoIf(Word32And(c, non_ascii_mask), &return_true); | 
|  | 27 | 
|  | 28     GotoIf(Int32LessThan(c, Int32Constant('A')), &out); | 
|  | 29     GotoIf(Int32GreaterThan(c, Int32Constant('Z')), &out); | 
|  | 30     Goto(&return_true); | 
|  | 31 | 
|  | 32     BIND(&return_true); | 
|  | 33     var_result.Bind(Int32Constant(1)); | 
|  | 34     Goto(&out); | 
|  | 35 | 
|  | 36     BIND(&out); | 
|  | 37     return var_result.value(); | 
|  | 38   } | 
|  | 39 }; | 
|  | 40 | 
|  | 41 TF_BUILTIN(StringPrototypeToLowerCaseIntl, IntlBuiltinsAssembler) { | 
|  | 42   Node* const maybe_string = Parameter(Descriptor::kReceiver); | 
|  | 43   Node* const context = Parameter(Descriptor::kContext); | 
|  | 44 | 
|  | 45   Node* const string = | 
|  | 46       ToThisString(context, maybe_string, "String.prototype.toLowerCase"); | 
|  | 47 | 
|  | 48   Label call_c(this), return_string(this), runtime(this, Label::kDeferred); | 
|  | 49 | 
|  | 50   // Early exit on empty strings. | 
|  | 51   Node* const length = SmiUntag(LoadStringLength(string)); | 
|  | 52   GotoIf(IntPtrEqual(length, IntPtrConstant(0)), &return_string); | 
|  | 53 | 
|  | 54   // Unpack strings if possible, and bail to runtime unless we get a one-byte | 
|  | 55   // flat string. | 
|  | 56   ToDirectStringAssembler to_direct( | 
|  | 57       state(), string, ToDirectStringAssembler::kDontUnpackSlicedStrings); | 
|  | 58   to_direct.TryToDirect(&runtime); | 
|  | 59 | 
|  | 60   GotoIfNot(IsOneByteStringInstanceType(to_direct.instance_type()), &runtime); | 
|  | 61 | 
|  | 62   // For short strings, do the conversion in CSA through the lookup table. | 
|  | 63 | 
|  | 64   Node* const dst = AllocateSeqOneByteString(context, length); | 
|  | 65 | 
|  | 66   const int kMaxShortStringLength = 24;  // Determined empirically. | 
|  | 67   GotoIf(IntPtrGreaterThan(length, IntPtrConstant(kMaxShortStringLength)), | 
|  | 68          &call_c); | 
|  | 69 | 
|  | 70   { | 
|  | 71     Node* const dst_ptr = PointerToSeqStringData(dst); | 
|  | 72     VARIABLE(var_cursor, MachineType::PointerRepresentation(), | 
|  | 73              IntPtrConstant(0)); | 
|  | 74 | 
|  | 75     Node* const start_address = to_direct.PointerToData(&call_c); | 
|  | 76     Node* const end_address = IntPtrAdd(start_address, length); | 
|  | 77 | 
|  | 78     Node* const to_lower_table_addr = ExternalConstant( | 
|  | 79         ExternalReference::intl_to_latin1_lower_table(isolate())); | 
|  | 80 | 
|  | 81     VariableList push_vars({&var_cursor}, zone()); | 
|  | 82     BuildFastLoop( | 
|  | 83         push_vars, start_address, end_address, | 
|  | 84         [=, &var_cursor](Node* current) { | 
|  | 85           Node* c = ChangeInt32ToIntPtr(Load(MachineType::Uint8(), current)); | 
|  | 86           Node* lower = Load(MachineType::Uint8(), to_lower_table_addr, c); | 
|  | 87           StoreNoWriteBarrier(MachineRepresentation::kWord8, dst_ptr, | 
|  | 88                               var_cursor.value(), lower); | 
|  | 89           Increment(var_cursor); | 
|  | 90         }, | 
|  | 91         kCharSize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); | 
|  | 92 | 
|  | 93     // All lower-case. | 
|  | 94     Return(dst); | 
|  | 95   } | 
|  | 96 | 
|  | 97   // Call into C for case conversion. The signature is: | 
|  | 98   // Object* ConvertOneByteToLower(String* src, String* dst, Isolate* isolate); | 
|  | 99   BIND(&call_c); | 
|  | 100   { | 
|  | 101     Node* const src = string; | 
|  | 102 | 
|  | 103     Node* const function_addr = ExternalConstant( | 
|  | 104         ExternalReference::intl_convert_one_byte_to_lower(isolate())); | 
|  | 105     Node* const isolate_ptr = | 
|  | 106         ExternalConstant(ExternalReference::isolate_address(isolate())); | 
|  | 107 | 
|  | 108     MachineType type_ptr = MachineType::Pointer(); | 
|  | 109     MachineType type_tagged = MachineType::AnyTagged(); | 
|  | 110 | 
|  | 111     Node* const result = | 
|  | 112         CallCFunction3(type_tagged, type_tagged, type_tagged, type_ptr, | 
|  | 113                        function_addr, src, dst, isolate_ptr); | 
|  | 114 | 
|  | 115     Return(result); | 
|  | 116   } | 
|  | 117 | 
|  | 118   BIND(&return_string); | 
|  | 119   Return(string); | 
|  | 120 | 
|  | 121   BIND(&runtime); | 
|  | 122   { | 
|  | 123     Node* const result = | 
|  | 124         CallRuntime(Runtime::kStringToLowerCaseIntl, context, string); | 
|  | 125     Return(result); | 
|  | 126   } | 
|  | 127 } | 
|  | 128 | 
|  | 129 }  // namespace internal | 
|  | 130 }  // namespace v8 | 
| OLD | NEW | 
|---|