Commit c60cb90c authored by franzih's avatar franzih Committed by Commit bot

[builtins] Move EncodeURI from runtime to builtins.

Repackage encodeURI and encodeURIComponent as builtin functions
and install them in the bootstrapper.

Crude benchmark on 351 encodeURI and encodeURIComponent tests averaged
over five runs:

* builtin functions
real	0m8.01s
user	0m18.00s
sys	0m7.37s

* JS functions calling into the runtime e.g., for %NewString
real	0m8.44s
user	0m19.52s
sys	0m7.49s

By running:
$ time tools/run-tests.py   --arch=x64 --mode=Release --buildbot
mjsunit/uri test262/built-ins/encodeURI*
>>> Running tests for x64.Release

BUG=v8:4912
R=yangguo@chromium.org

Review-Url: https://codereview.chromium.org/1983593002
Cr-Commit-Position: refs/heads/master@{#36273}
parent f248a83d
......@@ -320,7 +320,7 @@ config("toolchain") {
template("v8_source_set") {
source_set(target_name) {
forward_variables_from(invoker, "*", ["configs"])
forward_variables_from(invoker, "*", [ "configs" ])
configs += invoker.configs
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
......@@ -667,9 +667,7 @@ v8_source_set("v8_nosnapshot") {
"src/snapshot/snapshot-empty.cc",
]
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
}
v8_source_set("v8_snapshot") {
......@@ -701,9 +699,7 @@ v8_source_set("v8_snapshot") {
"$target_gen_dir/snapshot.cc",
]
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
}
if (v8_use_external_startup_data) {
......@@ -727,9 +723,7 @@ if (v8_use_external_startup_data) {
"src/snapshot/snapshot-external.cc",
]
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
}
}
......@@ -1476,6 +1470,8 @@ v8_source_set("v8_base") {
"src/unicode-inl.h",
"src/unicode.cc",
"src/unicode.h",
"src/uri.cc",
"src/uri.h",
"src/utils-inl.h",
"src/utils.cc",
"src/utils.h",
......@@ -1822,9 +1818,7 @@ v8_source_set("v8_base") {
]
}
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
defines = []
deps = [
......@@ -1917,9 +1911,7 @@ v8_source_set("v8_libbase") {
"src/base/utils/random-number-generator.h",
]
configs = [
":internal_config_base",
]
configs = [ ":internal_config_base" ]
defines = []
......@@ -1979,13 +1971,9 @@ v8_source_set("v8_libplatform") {
"src/libplatform/worker-thread.h",
]
configs = [
":internal_config_base",
]
configs = [ ":internal_config_base" ]
public_configs = [
":libplatform_config"
]
public_configs = [ ":libplatform_config" ]
deps = [
":v8_libbase",
......@@ -2000,9 +1988,7 @@ v8_source_set("fuzzer_support") {
"test/fuzzer/fuzzer-support.h",
]
configs = [
":internal_config_base",
]
configs = [ ":internal_config_base" ]
deps = [
snapshot_target,
......@@ -2158,9 +2144,7 @@ v8_source_set("json_fuzzer") {
":fuzzer_support",
]
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
}
v8_source_set("parser_fuzzer") {
......@@ -2172,9 +2156,7 @@ v8_source_set("parser_fuzzer") {
":fuzzer_support",
]
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
}
v8_source_set("regexp_fuzzer") {
......@@ -2186,9 +2168,7 @@ v8_source_set("regexp_fuzzer") {
":fuzzer_support",
]
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
}
v8_source_set("wasm_fuzzer") {
......@@ -2200,9 +2180,7 @@ v8_source_set("wasm_fuzzer") {
":fuzzer_support",
]
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
}
v8_source_set("wasm_asmjs_fuzzer") {
......@@ -2214,7 +2192,5 @@ v8_source_set("wasm_asmjs_fuzzer") {
":fuzzer_support",
]
configs = [
":internal_config",
]
configs = [ ":internal_config" ]
}
......@@ -2819,11 +2819,22 @@ bool Genesis::InstallNatives(GlobalContextType context_type) {
native_context()->set_string_function_prototype_map(
HeapObject::cast(string_function->initial_map()->prototype())->map());
Handle<JSGlobalObject> global_object =
handle(native_context()->global_object());
// Install Global.encodeURI.
SimpleInstallFunction(global_object, "encodeURI", Builtins::kGlobalEncodeURI,
1, false);
// Install Global.encodeURIComponent.
SimpleInstallFunction(global_object, "encodeURIComponent",
Builtins::kGlobalEncodeURIComponent, 1, false);
// Install Global.eval.
{
Handle<JSFunction> eval = SimpleInstallFunction(
handle(native_context()->global_object()), factory()->eval_string(),
Builtins::kGlobalEval, 1, false);
Handle<JSFunction> eval =
SimpleInstallFunction(global_object, factory()->eval_string(),
Builtins::kGlobalEval, 1, false);
native_context()->set_global_eval_fun(*eval);
}
......@@ -2866,8 +2877,7 @@ bool Genesis::InstallNatives(GlobalContextType context_type) {
{
Handle<String> key = factory()->Promise_string();
Handle<JSFunction> function = Handle<JSFunction>::cast(
JSReceiver::GetProperty(handle(native_context()->global_object()), key)
.ToHandleChecked());
JSReceiver::GetProperty(global_object, key).ToHandleChecked());
JSFunction::EnsureHasInitialMap(function);
function->initial_map()->set_instance_type(JS_PROMISE_TYPE);
function->shared()->set_construct_stub(
......
......@@ -23,6 +23,7 @@
#include "src/property-descriptor.h"
#include "src/prototype.h"
#include "src/string-builder.h"
#include "src/uri.h"
#include "src/vm-state-inl.h"
namespace v8 {
......@@ -2106,6 +2107,26 @@ BUILTIN(ObjectSeal) {
return *object;
}
// ES6 section 18.2.6.4 encodeURI (uri)
BUILTIN(GlobalEncodeURI) {
HandleScope scope(isolate);
Handle<String> uri;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, uri, Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
return Uri::EncodeUri(isolate, uri);
}
// ES6 section 18.2.6.5 encodeURIComponenet (uriComponent)
BUILTIN(GlobalEncodeURIComponent) {
HandleScope scope(isolate);
Handle<String> uriComponent;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, uriComponent,
Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
return Uri::EncodeUriComponent(isolate, uriComponent);
}
namespace {
......
......@@ -116,6 +116,9 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
V(GeneratorFunctionConstructor, kTargetAndNewTarget) \
V(AsyncFunctionConstructor, kTargetAndNewTarget) \
\
V(GlobalEncodeURI, kNone) \
V(GlobalEncodeURIComponent, kNone) \
\
V(GlobalEval, kTarget) \
\
V(MathAcos, kNone) \
......
......@@ -219,18 +219,6 @@ function URIDecodeComponent(component) {
return Decode(component, reservedPredicate);
}
// ECMA-262 - 15.1.3.3.
function URIEncode(uri) {
uri = TO_STRING(uri);
return %URIEncode(uri, true);
}
// ECMA-262 - 15.1.3.4
function URIEncodeComponent(component) {
component = TO_STRING(component);
return %URIEncode(component, false);
}
// -------------------------------------------------------------------
// Install exported functions.
......@@ -240,9 +228,7 @@ utils.InstallFunctions(global, DONT_ENUM, [
"escape", URIEscapeJS,
"unescape", URIUnescapeJS,
"decodeURI", URIDecode,
"decodeURIComponent", URIDecodeComponent,
"encodeURI", URIEncode,
"encodeURIComponent", URIEncodeComponent
"decodeURIComponent", URIDecodeComponent
]);
})
......@@ -5,7 +5,6 @@
#include "src/runtime/runtime-utils.h"
#include "src/arguments.h"
#include "src/char-predicates-inl.h"
#include "src/regexp/jsregexp-inl.h"
#include "src/string-builder.h"
#include "src/string-search.h"
......@@ -1152,131 +1151,6 @@ RUNTIME_FUNCTION(Runtime_NewString) {
return *result;
}
// anonymous namespace for URIEncode helper functions
namespace {
bool IsUnescapePredicateInUriComponent(uc16 c) {
if (IsAlphaNumeric(c)) {
return true;
}
switch (c) {
case '!':
case '\'':
case '(':
case ')':
case '*':
case '-':
case '.':
case '_':
case '~':
return true;
default:
return false;
}
}
bool IsUriSeparator(uc16 c) {
switch (c) {
case '#':
case ':':
case ';':
case '/':
case '?':
case '$':
case '&':
case '+':
case ',':
case '@':
case '=':
return true;
default:
return false;
}
}
void AddHexEncodedToBuffer(uint8_t octet, List<uint8_t>* buffer) {
buffer->Add('%');
buffer->Add(HexCharOfValue(octet >> 4));
buffer->Add(HexCharOfValue(octet & 0x0F));
}
void EncodeSingle(uc16 c, List<uint8_t>* buffer) {
uint8_t x = (c >> 12) & 0xF;
uint8_t y = (c >> 6) & 63;
uint8_t z = c & 63;
if (c <= 0x007F) {
AddHexEncodedToBuffer(c, buffer);
} else if (c <= 0x07FF) {
AddHexEncodedToBuffer(y + 192, buffer);
AddHexEncodedToBuffer(z + 128, buffer);
} else {
AddHexEncodedToBuffer(x + 224, buffer);
AddHexEncodedToBuffer(y + 128, buffer);
AddHexEncodedToBuffer(z + 128, buffer);
}
}
void EncodePair(uc16 cc1, uc16 cc2, List<uint8_t>* buffer) {
uint8_t u = ((cc1 >> 6) & 0xF) + 1;
uint8_t w = (cc1 >> 2) & 0xF;
uint8_t x = cc1 & 3;
uint8_t y = (cc2 >> 6) & 0xF;
uint8_t z = cc2 & 63;
AddHexEncodedToBuffer((u >> 2) + 240, buffer);
AddHexEncodedToBuffer((((u & 3) << 4) | w) + 128, buffer);
AddHexEncodedToBuffer(((x << 4) | y) + 128, buffer);
AddHexEncodedToBuffer(z + 128, buffer);
}
} // anonymous namespace
RUNTIME_FUNCTION(Runtime_URIEncode) {
HandleScope scope(isolate);
DCHECK(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, uri, 0);
CONVERT_BOOLEAN_ARG_CHECKED(is_uri, 1);
uri = String::Flatten(uri);
int uri_length = uri->length();
List<uint8_t> buffer(uri_length);
{
DisallowHeapAllocation no_gc;
String::FlatContent uri_content = uri->GetFlatContent();
for (int k = 0; k < uri_length; k++) {
uc16 cc1 = uri_content.Get(k);
if (unibrow::Utf16::IsLeadSurrogate(cc1)) {
k++;
if (k < uri_length) {
uc16 cc2 = uri->Get(k);
if (unibrow::Utf16::IsTrailSurrogate(cc2)) {
EncodePair(cc1, cc2, &buffer);
continue;
}
}
} else if (!unibrow::Utf16::IsTrailSurrogate(cc1)) {
if (IsUnescapePredicateInUriComponent(cc1) ||
(is_uri && IsUriSeparator(cc1))) {
buffer.Add(cc1);
} else {
EncodeSingle(cc1, &buffer);
}
continue;
}
AllowHeapAllocation allocate_error_and_return;
THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewURIError());
}
}
Handle<String> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
isolate->factory()->NewStringFromOneByte(buffer.ToConstVector()));
return *result;
}
RUNTIME_FUNCTION(Runtime_StringLessThan) {
HandleScope handle_scope(isolate);
......
......@@ -836,7 +836,6 @@ namespace internal {
F(StringTrim, 3, 1) \
F(TruncateString, 2, 1) \
F(NewString, 2, 1) \
F(URIEncode, 2, 1) \
F(StringLessThan, 2, 1) \
F(StringLessThanOrEqual, 2, 1) \
F(StringGreaterThan, 2, 1) \
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/uri.h"
#include "src/char-predicates-inl.h"
#include "src/handles.h"
#include "src/isolate-inl.h"
#include "src/list.h"
namespace v8 {
namespace internal {
namespace { // anonymous namespace for EncodeURI helper functions
bool IsUnescapePredicateInUriComponent(uc16 c) {
if (IsAlphaNumeric(c)) {
return true;
}
switch (c) {
case '!':
case '\'':
case '(':
case ')':
case '*':
case '-':
case '.':
case '_':
case '~':
return true;
default:
return false;
}
}
bool IsUriSeparator(uc16 c) {
switch (c) {
case '#':
case ':':
case ';':
case '/':
case '?':
case '$':
case '&':
case '+':
case ',':
case '@':
case '=':
return true;
default:
return false;
}
}
void AddHexEncodedToBuffer(uint8_t octet, List<uint8_t>* buffer) {
buffer->Add('%');
buffer->Add(HexCharOfValue(octet >> 4));
buffer->Add(HexCharOfValue(octet & 0x0F));
}
void EncodeSingle(uc16 c, List<uint8_t>* buffer) {
uint8_t x = (c >> 12) & 0xF;
uint8_t y = (c >> 6) & 63;
uint8_t z = c & 63;
if (c <= 0x007F) {
AddHexEncodedToBuffer(c, buffer);
} else if (c <= 0x07FF) {
AddHexEncodedToBuffer(y + 192, buffer);
AddHexEncodedToBuffer(z + 128, buffer);
} else {
AddHexEncodedToBuffer(x + 224, buffer);
AddHexEncodedToBuffer(y + 128, buffer);
AddHexEncodedToBuffer(z + 128, buffer);
}
}
void EncodePair(uc16 cc1, uc16 cc2, List<uint8_t>* buffer) {
uint8_t u = ((cc1 >> 6) & 0xF) + 1;
uint8_t w = (cc1 >> 2) & 0xF;
uint8_t x = cc1 & 3;
uint8_t y = (cc2 >> 6) & 0xF;
uint8_t z = cc2 & 63;
AddHexEncodedToBuffer((u >> 2) + 240, buffer);
AddHexEncodedToBuffer((((u & 3) << 4) | w) + 128, buffer);
AddHexEncodedToBuffer(((x << 4) | y) + 128, buffer);
AddHexEncodedToBuffer(z + 128, buffer);
}
} // anonymous namespace
Object* Uri::Encode(Isolate* isolate, Handle<String> uri, bool is_uri) {
uri = String::Flatten(uri);
int uri_length = uri->length();
List<uint8_t> buffer(uri_length);
{
DisallowHeapAllocation no_gc;
String::FlatContent uri_content = uri->GetFlatContent();
for (int k = 0; k < uri_length; k++) {
uc16 cc1 = uri_content.Get(k);
if (unibrow::Utf16::IsLeadSurrogate(cc1)) {
k++;
if (k < uri_length) {
uc16 cc2 = uri->Get(k);
if (unibrow::Utf16::IsTrailSurrogate(cc2)) {
EncodePair(cc1, cc2, &buffer);
continue;
}
}
} else if (!unibrow::Utf16::IsTrailSurrogate(cc1)) {
if (IsUnescapePredicateInUriComponent(cc1) ||
(is_uri && IsUriSeparator(cc1))) {
buffer.Add(cc1);
} else {
EncodeSingle(cc1, &buffer);
}
continue;
}
AllowHeapAllocation allocate_error_and_return;
THROW_NEW_ERROR_RETURN_FAILURE(isolate, NewURIError());
}
}
Handle<String> result;
ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
isolate, result,
isolate->factory()->NewStringFromOneByte(buffer.ToConstVector()));
return *result;
}
} // namespace internal
} // namespace v8
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_URI_H_
#define V8_URI_H_
#include "src/allocation.h"
#include "src/objects.h"
namespace v8 {
namespace internal {
class Uri : public AllStatic {
public:
static Object* EncodeUri(Isolate* isolate, Handle<String> uri) {
return Encode(isolate, uri, true);
}
static Object* EncodeUriComponent(Isolate* isolate,
Handle<String> component) {
return Encode(isolate, component, false);
}
// DecodeUri
// DecodeUriComponent
// escape
// unescape
private:
static Object* Encode(Isolate* isolate, Handle<String> uri, bool is_uri);
// decode
};
} // namespace internal
} // namespace v8
#endif // V8_URI_H_
......@@ -1131,6 +1131,8 @@
'unicode-cache.h',
'unicode-decoder.cc',
'unicode-decoder.h',
'uri.cc',
'uri.h',
'utils-inl.h',
'utils.cc',
'utils.h',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment