1 // Copyright 2016 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 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins.h" 7 #include "src/code-factory.h" 8 #include "src/code-stub-assembler.h" 9 #include "src/compiler.h" 10 #include "src/counters.h" 11 #include "src/objects-inl.h" 12 #include "src/uri.h" 13 14 namespace v8 { 15 namespace internal { 16 17 // ES6 section 18.2.6.2 decodeURI (encodedURI) 18 BUILTIN(GlobalDecodeURI) { 19 HandleScope scope(isolate); 20 Handle<String> encoded_uri; 21 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 22 isolate, encoded_uri, 23 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 24 25 RETURN_RESULT_OR_FAILURE(isolate, Uri::DecodeUri(isolate, encoded_uri)); 26 } 27 28 // ES6 section 18.2.6.3 decodeURIComponent (encodedURIComponent) 29 BUILTIN(GlobalDecodeURIComponent) { 30 HandleScope scope(isolate); 31 Handle<String> encoded_uri_component; 32 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 33 isolate, encoded_uri_component, 34 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 35 36 RETURN_RESULT_OR_FAILURE( 37 isolate, Uri::DecodeUriComponent(isolate, encoded_uri_component)); 38 } 39 40 // ES6 section 18.2.6.4 encodeURI (uri) 41 BUILTIN(GlobalEncodeURI) { 42 HandleScope scope(isolate); 43 Handle<String> uri; 44 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 45 isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 46 47 RETURN_RESULT_OR_FAILURE(isolate, Uri::EncodeUri(isolate, uri)); 48 } 49 50 // ES6 section 18.2.6.5 encodeURIComponenet (uriComponent) 51 BUILTIN(GlobalEncodeURIComponent) { 52 HandleScope scope(isolate); 53 Handle<String> uri_component; 54 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 55 isolate, uri_component, 56 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 57 58 RETURN_RESULT_OR_FAILURE(isolate, 59 Uri::EncodeUriComponent(isolate, uri_component)); 60 } 61 62 // ES6 section B.2.1.1 escape (string) 63 BUILTIN(GlobalEscape) { 64 HandleScope scope(isolate); 65 Handle<String> string; 66 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 67 isolate, string, 68 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 69 70 RETURN_RESULT_OR_FAILURE(isolate, Uri::Escape(isolate, string)); 71 } 72 73 // ES6 section B.2.1.2 unescape (string) 74 BUILTIN(GlobalUnescape) { 75 HandleScope scope(isolate); 76 Handle<String> string; 77 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 78 isolate, string, 79 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 80 81 RETURN_RESULT_OR_FAILURE(isolate, Uri::Unescape(isolate, string)); 82 } 83 84 // ES6 section 18.2.1 eval (x) 85 BUILTIN(GlobalEval) { 86 HandleScope scope(isolate); 87 Handle<Object> x = args.atOrUndefined(isolate, 1); 88 Handle<JSFunction> target = args.target(); 89 Handle<JSObject> target_global_proxy(target->global_proxy(), isolate); 90 if (!x->IsString()) return *x; 91 if (!Builtins::AllowDynamicFunction(isolate, target, target_global_proxy)) { 92 isolate->CountUsage(v8::Isolate::kFunctionConstructorReturnedUndefined); 93 return isolate->heap()->undefined_value(); 94 } 95 Handle<JSFunction> function; 96 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 97 isolate, function, 98 Compiler::GetFunctionFromString(handle(target->native_context(), isolate), 99 Handle<String>::cast(x), 100 NO_PARSE_RESTRICTION, kNoSourcePosition)); 101 RETURN_RESULT_OR_FAILURE( 102 isolate, 103 Execution::Call(isolate, function, target_global_proxy, 0, nullptr)); 104 } 105 106 // ES6 section 18.2.2 isFinite ( number ) 107 void Builtins::Generate_GlobalIsFinite(compiler::CodeAssemblerState* state) { 108 typedef CodeStubAssembler::Label Label; 109 typedef compiler::Node Node; 110 typedef CodeStubAssembler::Variable Variable; 111 CodeStubAssembler assembler(state); 112 113 Node* context = assembler.Parameter(4); 114 115 Label return_true(&assembler), return_false(&assembler); 116 117 // We might need to loop once for ToNumber conversion. 118 Variable var_num(&assembler, MachineRepresentation::kTagged); 119 Label loop(&assembler, &var_num); 120 var_num.Bind(assembler.Parameter(1)); 121 assembler.Goto(&loop); 122 assembler.Bind(&loop); 123 { 124 // Load the current {num} value. 125 Node* num = var_num.value(); 126 127 // Check if {num} is a Smi or a HeapObject. 128 assembler.GotoIf(assembler.TaggedIsSmi(num), &return_true); 129 130 // Check if {num} is a HeapNumber. 131 Label if_numisheapnumber(&assembler), 132 if_numisnotheapnumber(&assembler, Label::kDeferred); 133 assembler.Branch(assembler.IsHeapNumberMap(assembler.LoadMap(num)), 134 &if_numisheapnumber, &if_numisnotheapnumber); 135 136 assembler.Bind(&if_numisheapnumber); 137 { 138 // Check if {num} contains a finite, non-NaN value. 139 Node* num_value = assembler.LoadHeapNumberValue(num); 140 assembler.BranchIfFloat64IsNaN(assembler.Float64Sub(num_value, num_value), 141 &return_false, &return_true); 142 } 143 144 assembler.Bind(&if_numisnotheapnumber); 145 { 146 // Need to convert {num} to a Number first. 147 Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate()); 148 var_num.Bind(assembler.CallStub(callable, context, num)); 149 assembler.Goto(&loop); 150 } 151 } 152 153 assembler.Bind(&return_true); 154 assembler.Return(assembler.BooleanConstant(true)); 155 156 assembler.Bind(&return_false); 157 assembler.Return(assembler.BooleanConstant(false)); 158 } 159 160 // ES6 section 18.2.3 isNaN ( number ) 161 void Builtins::Generate_GlobalIsNaN(compiler::CodeAssemblerState* state) { 162 typedef CodeStubAssembler::Label Label; 163 typedef compiler::Node Node; 164 typedef CodeStubAssembler::Variable Variable; 165 CodeStubAssembler assembler(state); 166 167 Node* context = assembler.Parameter(4); 168 169 Label return_true(&assembler), return_false(&assembler); 170 171 // We might need to loop once for ToNumber conversion. 172 Variable var_num(&assembler, MachineRepresentation::kTagged); 173 Label loop(&assembler, &var_num); 174 var_num.Bind(assembler.Parameter(1)); 175 assembler.Goto(&loop); 176 assembler.Bind(&loop); 177 { 178 // Load the current {num} value. 179 Node* num = var_num.value(); 180 181 // Check if {num} is a Smi or a HeapObject. 182 assembler.GotoIf(assembler.TaggedIsSmi(num), &return_false); 183 184 // Check if {num} is a HeapNumber. 185 Label if_numisheapnumber(&assembler), 186 if_numisnotheapnumber(&assembler, Label::kDeferred); 187 assembler.Branch(assembler.IsHeapNumberMap(assembler.LoadMap(num)), 188 &if_numisheapnumber, &if_numisnotheapnumber); 189 190 assembler.Bind(&if_numisheapnumber); 191 { 192 // Check if {num} contains a NaN. 193 Node* num_value = assembler.LoadHeapNumberValue(num); 194 assembler.BranchIfFloat64IsNaN(num_value, &return_true, &return_false); 195 } 196 197 assembler.Bind(&if_numisnotheapnumber); 198 { 199 // Need to convert {num} to a Number first. 200 Callable callable = CodeFactory::NonNumberToNumber(assembler.isolate()); 201 var_num.Bind(assembler.CallStub(callable, context, num)); 202 assembler.Goto(&loop); 203 } 204 } 205 206 assembler.Bind(&return_true); 207 assembler.Return(assembler.BooleanConstant(true)); 208 209 assembler.Bind(&return_false); 210 assembler.Return(assembler.BooleanConstant(false)); 211 } 212 213 } // namespace internal 214 } // namespace v8 215