Commit 5819e4be authored by vogelheim's avatar vogelheim Committed by Commit bot

Re-re-land FastAccessorBuilder.

... using the RawMachineAssembler and the work in crrev.com/1407313004.

The original change collided with crrev.com/1513543003.

BUG=chromium:508898
LOG=Y

Committed: https://crrev.com/515d9ccd8e6df7bf2ca01e2a55aaad30226399e1
Cr-Commit-Position: refs/heads/master@{#32742}

patch from issue 1474543004 at patchset 260001 (http://crrev.com/1474543004#ps260001)

Committed: https://crrev.com/ee5c38d7db907ff86dd4049721c0cb4bc90a6c4d
Cr-Commit-Position: refs/heads/master@{#32753}

patch from issue 1504713012 at patchset 20001 (http://crrev.com/1504713012#ps20001)

Review URL: https://codereview.chromium.org/1518703002

Cr-Commit-Position: refs/heads/master@{#32786}
parent a86ddc5b
...@@ -597,6 +597,7 @@ source_set("v8_base") { ...@@ -597,6 +597,7 @@ source_set("v8_base") {
sources = [ sources = [
"include/v8-debug.h", "include/v8-debug.h",
"include/v8-experimental.h",
"include/v8-platform.h", "include/v8-platform.h",
"include/v8-profiler.h", "include/v8-profiler.h",
"include/v8-testing.h", "include/v8-testing.h",
...@@ -614,6 +615,8 @@ source_set("v8_base") { ...@@ -614,6 +615,8 @@ source_set("v8_base") {
"src/allocation-site-scopes.h", "src/allocation-site-scopes.h",
"src/api.cc", "src/api.cc",
"src/api.h", "src/api.h",
"src/api-experimental.cc",
"src/api-experimental.h",
"src/api-natives.cc", "src/api-natives.cc",
"src/api-natives.h", "src/api-natives.h",
"src/arguments.cc", "src/arguments.cc",
...@@ -725,6 +728,8 @@ source_set("v8_base") { ...@@ -725,6 +728,8 @@ source_set("v8_base") {
"src/compiler/escape-analysis.h", "src/compiler/escape-analysis.h",
"src/compiler/escape-analysis-reducer.cc", "src/compiler/escape-analysis-reducer.cc",
"src/compiler/escape-analysis-reducer.h", "src/compiler/escape-analysis-reducer.h",
"src/compiler/fast-accessor-assembler.cc",
"src/compiler/fast-accessor-assembler.h",
"src/compiler/frame.cc", "src/compiler/frame.cc",
"src/compiler/frame.h", "src/compiler/frame.h",
"src/compiler/frame-elider.cc", "src/compiler/frame-elider.cc",
......
// Copyright 2015 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.
/**
* This header contains a set of experimental V8 APIs. We hope these will
* become a part of standard V8, but they may also be removed if we deem the
* experiment to not be successul.
*/
#ifndef V8_INCLUDE_V8_EXPERIMENTAL_H_
#define V8_INCLUDE_V8_EXPERIMENTAL_H_
#include "include/v8.h"
namespace v8 {
namespace experimental {
// Allow the embedder to construct accessors that V8 can compile and use
// directly, without jumping into the runtime.
class V8_EXPORT FastAccessorBuilder {
public:
struct ValueId {
size_t value_id;
};
struct LabelId {
size_t label_id;
};
static FastAccessorBuilder* New(Isolate* isolate);
ValueId IntegerConstant(int int_constant);
ValueId GetReceiver();
ValueId LoadInternalField(ValueId value_id, int field_no);
ValueId LoadValue(ValueId value_id, int offset);
ValueId LoadObject(ValueId value_id, int offset);
void ReturnValue(ValueId value_id);
void CheckFlagSetOrReturnNull(ValueId value_id, int mask);
void CheckNotZeroOrReturnNull(ValueId value_id);
LabelId MakeLabel();
void SetLabel(LabelId label_id);
void CheckNotZeroOrJump(ValueId value_id, LabelId label_id);
private:
FastAccessorBuilder() = delete;
FastAccessorBuilder(const FastAccessorBuilder&) = delete;
~FastAccessorBuilder() = delete;
void operator=(const FastAccessorBuilder&) = delete;
};
} // namespace experimental
} // namespace v8
#endif // V8_INCLUDE_V8_EXPERIMENTAL_H_
...@@ -136,6 +136,10 @@ class CallHandlerHelper; ...@@ -136,6 +136,10 @@ class CallHandlerHelper;
class EscapableHandleScope; class EscapableHandleScope;
template<typename T> class ReturnValue; template<typename T> class ReturnValue;
namespace experimental {
class FastAccessorBuilder;
} // namespace experimental
namespace internal { namespace internal {
class Arguments; class Arguments;
class Heap; class Heap;
...@@ -4417,7 +4421,8 @@ class V8_EXPORT FunctionTemplate : public Template { ...@@ -4417,7 +4421,8 @@ class V8_EXPORT FunctionTemplate : public Template {
* the callback cannot be null. * the callback cannot be null.
*/ */
static Local<FunctionTemplate> NewWithFastHandler( static Local<FunctionTemplate> NewWithFastHandler(
Isolate* isolate, FunctionCallback callback, Local<Value> fast_handler, Isolate* isolate, FunctionCallback callback,
experimental::FastAccessorBuilder* fast_handler = nullptr,
Local<Value> data = Local<Value>(), Local<Value> data = Local<Value>(),
Local<Signature> signature = Local<Signature>(), int length = 0); Local<Signature> signature = Local<Signature>(), int length = 0);
...@@ -4431,9 +4436,9 @@ class V8_EXPORT FunctionTemplate : public Template { ...@@ -4431,9 +4436,9 @@ class V8_EXPORT FunctionTemplate : public Template {
* callback is called whenever the function created from this * callback is called whenever the function created from this
* FunctionTemplate is called. * FunctionTemplate is called.
*/ */
void SetCallHandler(FunctionCallback callback, void SetCallHandler(
Local<Value> data = Local<Value>(), FunctionCallback callback, Local<Value> data = Local<Value>(),
Local<Value> fast_handler = Local<Value>()); experimental::FastAccessorBuilder* fast_handler = nullptr);
/** Set the predefined length property for the FunctionTemplate. */ /** Set the predefined length property for the FunctionTemplate. */
void SetLength(int length); void SetLength(int length);
......
...@@ -25,4 +25,7 @@ specific_include_rules = { ...@@ -25,4 +25,7 @@ specific_include_rules = {
"d8\.cc": [ "d8\.cc": [
"+include/libplatform/libplatform.h", "+include/libplatform/libplatform.h",
], ],
"api-experimental\.cc": [
"+src/compiler/fast-accessor-assembler.h",
],
} }
// Copyright 2015 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.
/**
* Implementation for v8-experimental.h.
*/
#include "src/api-experimental.h"
#include "include/v8.h"
#include "include/v8-experimental.h"
#include "src/api.h"
#include "src/compiler/fast-accessor-assembler.h"
namespace {
v8::internal::compiler::FastAccessorAssembler* FromApi(
v8::experimental::FastAccessorBuilder* builder) {
return reinterpret_cast<v8::internal::compiler::FastAccessorAssembler*>(
builder);
}
v8::experimental::FastAccessorBuilder* FromInternal(
v8::internal::compiler::FastAccessorAssembler* fast_accessor_assembler) {
return reinterpret_cast<v8::experimental::FastAccessorBuilder*>(
fast_accessor_assembler);
}
} // namespace
namespace v8 {
namespace internal {
namespace experimental {
MaybeHandle<Code> BuildCodeFromFastAccessorBuilder(
v8::experimental::FastAccessorBuilder* fast_handler) {
i::MaybeHandle<i::Code> code;
if (fast_handler != nullptr) {
auto faa = FromApi(fast_handler);
code = faa->Build();
CHECK(!code.is_null());
delete faa;
}
return code;
}
} // namespace experimental
} // namespace internal
namespace experimental {
FastAccessorBuilder* FastAccessorBuilder::New(Isolate* isolate) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
internal::compiler::FastAccessorAssembler* faa =
new internal::compiler::FastAccessorAssembler(i_isolate);
return FromInternal(faa);
}
FastAccessorBuilder::ValueId FastAccessorBuilder::IntegerConstant(
int const_value) {
return FromApi(this)->IntegerConstant(const_value);
}
FastAccessorBuilder::ValueId FastAccessorBuilder::GetReceiver() {
return FromApi(this)->GetReceiver();
}
FastAccessorBuilder::ValueId FastAccessorBuilder::LoadInternalField(
ValueId value, int field_no) {
return FromApi(this)->LoadInternalField(value, field_no);
}
FastAccessorBuilder::ValueId FastAccessorBuilder::LoadValue(ValueId value_id,
int offset) {
return FromApi(this)->LoadValue(value_id, offset);
}
FastAccessorBuilder::ValueId FastAccessorBuilder::LoadObject(ValueId value_id,
int offset) {
return FromApi(this)->LoadObject(value_id, offset);
}
void FastAccessorBuilder::ReturnValue(ValueId value) {
FromApi(this)->ReturnValue(value);
}
void FastAccessorBuilder::CheckFlagSetOrReturnNull(ValueId value_id, int mask) {
FromApi(this)->CheckFlagSetOrReturnNull(value_id, mask);
}
void FastAccessorBuilder::CheckNotZeroOrReturnNull(ValueId value_id) {
FromApi(this)->CheckNotZeroOrReturnNull(value_id);
}
FastAccessorBuilder::LabelId FastAccessorBuilder::MakeLabel() {
return FromApi(this)->MakeLabel();
}
void FastAccessorBuilder::SetLabel(LabelId label_id) {
FromApi(this)->SetLabel(label_id);
}
void FastAccessorBuilder::CheckNotZeroOrJump(ValueId value_id,
LabelId label_id) {
FromApi(this)->CheckNotZeroOrJump(value_id, label_id);
}
} // namespace experimental
} // namespace v8
// Copyright 2015 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_API_EXPERIMENTAL_H_
#define V8_API_EXPERIMENTAL_H_
#include "src/handles.h"
namespace v8 {
namespace internal {
class Code;
} // internal;
namespace experimental {
class FastAccessorBuilder;
} // experimental
namespace internal {
namespace experimental {
v8::internal::MaybeHandle<v8::internal::Code> BuildCodeFromFastAccessorBuilder(
v8::experimental::FastAccessorBuilder* fast_handler);
} // namespace experimental
} // namespace internal
} // namespace v8
#endif // V8_API_EXPERIMENTAL_H_
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
#include <limits> #include <limits>
#include <vector> #include <vector>
#include "include/v8-debug.h" #include "include/v8-debug.h"
#include "include/v8-experimental.h"
#include "include/v8-profiler.h" #include "include/v8-profiler.h"
#include "include/v8-testing.h" #include "include/v8-testing.h"
#include "src/api-experimental.h"
#include "src/api-natives.h" #include "src/api-natives.h"
#include "src/assert-scope.h" #include "src/assert-scope.h"
#include "src/background-parsing-task.h" #include "src/background-parsing-task.h"
...@@ -999,7 +1001,7 @@ void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) { ...@@ -999,7 +1001,7 @@ void FunctionTemplate::Inherit(v8::Local<FunctionTemplate> value) {
static Local<FunctionTemplate> FunctionTemplateNew( static Local<FunctionTemplate> FunctionTemplateNew(
i::Isolate* isolate, FunctionCallback callback, i::Isolate* isolate, FunctionCallback callback,
v8::Local<Value> fast_handler, v8::Local<Value> data, experimental::FastAccessorBuilder* fast_handler, v8::Local<Value> data,
v8::Local<Signature> signature, int length, bool do_not_cache) { v8::Local<Signature> signature, int length, bool do_not_cache) {
i::Handle<i::Struct> struct_obj = i::Handle<i::Struct> struct_obj =
isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE); isolate->factory()->NewStruct(i::FUNCTION_TEMPLATE_INFO_TYPE);
...@@ -1040,14 +1042,15 @@ Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate, ...@@ -1040,14 +1042,15 @@ Local<FunctionTemplate> FunctionTemplate::New(Isolate* isolate,
DCHECK(!i_isolate->serializer_enabled()); DCHECK(!i_isolate->serializer_enabled());
LOG_API(i_isolate, "FunctionTemplate::New"); LOG_API(i_isolate, "FunctionTemplate::New");
ENTER_V8(i_isolate); ENTER_V8(i_isolate);
return FunctionTemplateNew(i_isolate, callback, v8::Local<Value>(), data, return FunctionTemplateNew(i_isolate, callback, nullptr, data, signature,
signature, length, false); length, false);
} }
Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler( Local<FunctionTemplate> FunctionTemplate::NewWithFastHandler(
Isolate* isolate, FunctionCallback callback, v8::Local<Value> fast_handler, Isolate* isolate, FunctionCallback callback,
v8::Local<Value> data, v8::Local<Signature> signature, int length) { experimental::FastAccessorBuilder* fast_handler, v8::Local<Value> data,
v8::Local<Signature> signature, int length) {
// TODO(vogelheim): 'fast_handler' should have a more specific type than // TODO(vogelheim): 'fast_handler' should have a more specific type than
// Local<Value>. // Local<Value>.
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
...@@ -1077,9 +1080,9 @@ Local<AccessorSignature> AccessorSignature::New( ...@@ -1077,9 +1080,9 @@ Local<AccessorSignature> AccessorSignature::New(
} while (false) } while (false)
void FunctionTemplate::SetCallHandler(FunctionCallback callback, void FunctionTemplate::SetCallHandler(
v8::Local<Value> data, FunctionCallback callback, v8::Local<Value> data,
v8::Local<Value> fast_handler) { experimental::FastAccessorBuilder* fast_handler) {
auto info = Utils::OpenHandle(this); auto info = Utils::OpenHandle(this);
EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler"); EnsureNotInstantiated(info, "v8::FunctionTemplate::SetCallHandler");
i::Isolate* isolate = info->GetIsolate(); i::Isolate* isolate = info->GetIsolate();
...@@ -1090,10 +1093,10 @@ void FunctionTemplate::SetCallHandler(FunctionCallback callback, ...@@ -1090,10 +1093,10 @@ void FunctionTemplate::SetCallHandler(FunctionCallback callback,
i::Handle<i::CallHandlerInfo> obj = i::Handle<i::CallHandlerInfo> obj =
i::Handle<i::CallHandlerInfo>::cast(struct_obj); i::Handle<i::CallHandlerInfo>::cast(struct_obj);
SET_FIELD_WRAPPED(obj, set_callback, callback); SET_FIELD_WRAPPED(obj, set_callback, callback);
if (!fast_handler.IsEmpty()) { i::MaybeHandle<i::Code> code =
i::Handle<i::Object> code = Utils::OpenHandle(*fast_handler); i::experimental::BuildCodeFromFastAccessorBuilder(fast_handler);
CHECK(code->IsCode()); if (!code.is_null()) {
obj->set_fast_handler(*code); obj->set_fast_handler(*code.ToHandleChecked());
} }
if (data.IsEmpty()) { if (data.IsEmpty()) {
data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate)); data = v8::Undefined(reinterpret_cast<v8::Isolate*>(isolate));
...@@ -4318,7 +4321,7 @@ MaybeLocal<Function> Function::New(Local<Context> context, ...@@ -4318,7 +4321,7 @@ MaybeLocal<Function> Function::New(Local<Context> context,
i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate(); i::Isolate* isolate = Utils::OpenHandle(*context)->GetIsolate();
LOG_API(isolate, "Function::New"); LOG_API(isolate, "Function::New");
ENTER_V8(isolate); ENTER_V8(isolate);
return FunctionTemplateNew(isolate, callback, Local<Value>(), data, return FunctionTemplateNew(isolate, callback, nullptr, data,
Local<Signature>(), length, true) Local<Signature>(), length, true)
->GetFunction(context); ->GetFunction(context);
} }
......
// Copyright 2015 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/compiler/fast-accessor-assembler.h"
#include "src/base/logging.h"
#include "src/compiler/graph.h"
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/raw-machine-assembler.h"
#include "src/compiler/schedule.h"
#include "src/compiler/verifier.h"
#include "src/handles-inl.h"
#include "src/objects.h" // For FAA::GetInternalField impl.
namespace v8 {
namespace internal {
namespace compiler {
FastAccessorAssembler::FastAccessorAssembler(Isolate* isolate)
: zone_(),
assembler_(new RawMachineAssembler(
isolate, new (zone()) Graph(zone()),
Linkage::GetJSCallDescriptor(&zone_, false, 1,
CallDescriptor::kNoFlags))),
state_(kBuilding) {}
FastAccessorAssembler::~FastAccessorAssembler() {}
FastAccessorAssembler::ValueId FastAccessorAssembler::IntegerConstant(
int const_value) {
CHECK_EQ(kBuilding, state_);
return FromRaw(assembler_->NumberConstant(const_value));
}
FastAccessorAssembler::ValueId FastAccessorAssembler::GetReceiver() {
CHECK_EQ(kBuilding, state_);
// For JS call descriptor, the receiver is parameter 0. If we use other
// call descriptors, this may or may not hold. So let's check.
CHECK(assembler_->call_descriptor()->IsJSFunctionCall());
return FromRaw(assembler_->Parameter(0));
}
FastAccessorAssembler::ValueId FastAccessorAssembler::LoadInternalField(
ValueId value, int field_no) {
CHECK_EQ(kBuilding, state_);
// Determine the 'value' object's instance type.
Node* object_map =
assembler_->Load(MachineType::Pointer(), FromId(value),
assembler_->IntPtrConstant(
Internals::kHeapObjectMapOffset - kHeapObjectTag));
Node* instance_type = assembler_->WordAnd(
assembler_->Load(
MachineType::Uint16(), object_map,
assembler_->IntPtrConstant(
Internals::kMapInstanceTypeAndBitFieldOffset - kHeapObjectTag)),
assembler_->IntPtrConstant(0xff));
// Check whether we have a proper JSObject.
RawMachineLabel is_jsobject, is_not_jsobject, merge;
assembler_->Branch(
assembler_->WordEqual(
instance_type, assembler_->IntPtrConstant(Internals::kJSObjectType)),
&is_jsobject, &is_not_jsobject);
// JSObject? Then load the internal field field_no.
assembler_->Bind(&is_jsobject);
Node* internal_field = assembler_->Load(
MachineType::Pointer(), FromId(value),
assembler_->IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag +
kPointerSize * field_no));
assembler_->Goto(&merge);
// No JSObject? Return undefined.
// TODO(vogelheim): Check whether this is the appropriate action, or whether
// the method should take a label instead.
assembler_->Bind(&is_not_jsobject);
Node* fail_value = assembler_->UndefinedConstant();
assembler_->Goto(&merge);
// Return.
assembler_->Bind(&merge);
Node* phi = assembler_->Phi(MachineRepresentation::kTagged, internal_field,
fail_value);
return FromRaw(phi);
}
FastAccessorAssembler::ValueId FastAccessorAssembler::LoadValue(ValueId value,
int offset) {
CHECK_EQ(kBuilding, state_);
return FromRaw(assembler_->Load(MachineType::IntPtr(), FromId(value),
assembler_->IntPtrConstant(offset)));
}
FastAccessorAssembler::ValueId FastAccessorAssembler::LoadObject(ValueId value,
int offset) {
CHECK_EQ(kBuilding, state_);
return FromRaw(
assembler_->Load(MachineType::AnyTagged(),
assembler_->Load(MachineType::Pointer(), FromId(value),
assembler_->IntPtrConstant(offset))));
}
void FastAccessorAssembler::ReturnValue(ValueId value) {
CHECK_EQ(kBuilding, state_);
assembler_->Return(FromId(value));
}
void FastAccessorAssembler::CheckFlagSetOrReturnNull(ValueId value, int mask) {
CHECK_EQ(kBuilding, state_);
RawMachineLabel pass, fail;
assembler_->Branch(
assembler_->Word32Equal(
assembler_->Word32And(FromId(value), assembler_->Int32Constant(mask)),
assembler_->Int32Constant(0)),
&pass, &fail);
assembler_->Bind(&fail);
assembler_->Return(assembler_->NullConstant());
assembler_->Bind(&pass);
}
void FastAccessorAssembler::CheckNotZeroOrReturnNull(ValueId value) {
CHECK_EQ(kBuilding, state_);
RawMachineLabel is_null, not_null;
assembler_->Branch(
assembler_->IntPtrEqual(FromId(value), assembler_->IntPtrConstant(0)),
&is_null, &not_null);
assembler_->Bind(&is_null);
assembler_->Return(assembler_->NullConstant());
assembler_->Bind(&not_null);
}
FastAccessorAssembler::LabelId FastAccessorAssembler::MakeLabel() {
CHECK_EQ(kBuilding, state_);
RawMachineLabel* label =
new (zone()->New(sizeof(RawMachineLabel))) RawMachineLabel;
return FromRaw(label);
}
void FastAccessorAssembler::SetLabel(LabelId label_id) {
CHECK_EQ(kBuilding, state_);
assembler_->Bind(FromId(label_id));
}
void FastAccessorAssembler::CheckNotZeroOrJump(ValueId value_id,
LabelId label_id) {
CHECK_EQ(kBuilding, state_);
RawMachineLabel pass;
assembler_->Branch(
assembler_->IntPtrEqual(FromId(value_id), assembler_->IntPtrConstant(0)),
&pass, FromId(label_id));
assembler_->Bind(&pass);
}
MaybeHandle<Code> FastAccessorAssembler::Build() {
CHECK_EQ(kBuilding, state_);
// Cleanup: We no longer need this.
nodes_.clear();
labels_.clear();
// Export the schedule and call the compiler.
CompilationInfo info("FastAccessorAssembler", assembler_->isolate(), zone());
Schedule* schedule = assembler_->Export();
// TODO(vogelheim): Pipeline should have a dedicated entry point for this
// assembler.
MaybeHandle<Code> code = Pipeline::GenerateCodeForTesting(
&info, assembler_->call_descriptor(), assembler_->graph(), schedule);
// Update state & return.
state_ = !code.is_null() ? kBuilt : kError;
return code;
}
FastAccessorAssembler::ValueId FastAccessorAssembler::FromRaw(Node* node) {
nodes_.push_back(node);
ValueId value = {nodes_.size() - 1};
return value;
}
FastAccessorAssembler::LabelId FastAccessorAssembler::FromRaw(
RawMachineLabel* label) {
labels_.push_back(label);
LabelId label_id = {labels_.size() - 1};
return label_id;
}
Node* FastAccessorAssembler::FromId(ValueId value) const {
CHECK_LT(value.value_id, nodes_.size());
CHECK_NOT_NULL(nodes_.at(value.value_id));
return nodes_.at(value.value_id);
}
RawMachineLabel* FastAccessorAssembler::FromId(LabelId label) const {
CHECK_LT(label.label_id, labels_.size());
CHECK_NOT_NULL(labels_.at(label.label_id));
return labels_.at(label.label_id);
}
} // namespace compiler
} // namespace internal
} // namespace v8
// Copyright 2015 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_COMPILER_FAST_ACCESSOR_ASSEMBLER_H_
#define V8_COMPILER_FAST_ACCESSOR_ASSEMBLER_H_
#include <stdint.h>
#include <vector>
// Clients of this interface shouldn't depend on lots of compiler internals.
// Do not include anything from src/compiler here!
#include "include/v8-experimental.h"
#include "src/base/macros.h"
#include "src/base/smart-pointers.h"
#include "src/handles.h"
namespace v8 {
namespace internal {
class Code;
class Isolate;
class Zone;
namespace compiler {
class Node;
class RawMachineAssembler;
class RawMachineLabel;
// This interface "exports" an aggregated subset of RawMachineAssembler, for
// use by the API to implement Fast Dom Accessors.
//
// This interface is made for this single purpose only and does not attempt
// to implement a general purpose solution. If you need one, please look at
// RawMachineAssembler instead.
//
// The life cycle of a FastAccessorAssembler has two phases:
// - After creating the instance, you can call an arbitrary sequence of
// builder functions to build the desired function.
// - When done, you can Build() the accessor and query for the build results.
//
// You cannot call any result getters before Build() was called & successful;
// and you cannot call any builder functions after Build() was called.
class FastAccessorAssembler {
public:
typedef v8::experimental::FastAccessorBuilder::ValueId ValueId;
typedef v8::experimental::FastAccessorBuilder::LabelId LabelId;
explicit FastAccessorAssembler(Isolate* isolate);
~FastAccessorAssembler();
// Builder / assembler functions:
ValueId IntegerConstant(int int_constant);
ValueId GetReceiver();
ValueId LoadInternalField(ValueId value_id, int field_no);
ValueId LoadValue(ValueId value_id, int offset);
ValueId LoadObject(ValueId value_id, int offset);
// Builder / assembler functions for control flow.
void ReturnValue(ValueId value_id);
void CheckFlagSetOrReturnNull(ValueId value_id, int mask);
void CheckNotZeroOrReturnNull(ValueId value_id);
// TODO(vogelheim): Implement a C++ callback.
// void CheckNotNullOrCallback(ValueId value_id, ..c++-callback type...,
// ValueId arg1, ValueId arg2, ...);
LabelId MakeLabel();
void SetLabel(LabelId label_id);
void CheckNotZeroOrJump(ValueId value_id, LabelId label_id);
// Assemble the code.
MaybeHandle<Code> Build();
private:
ValueId FromRaw(Node* node);
LabelId FromRaw(RawMachineLabel* label);
Node* FromId(ValueId value) const;
RawMachineLabel* FromId(LabelId value) const;
Zone* zone() { return &zone_; }
Zone zone_;
base::SmartPointer<RawMachineAssembler> assembler_;
// To prevent exposing the RMA internals to the outside world, we'll map
// Node + Label pointers integers wrapped in ValueId and LabelId instances.
// These vectors maintain this mapping.
std::vector<Node*> nodes_;
std::vector<RawMachineLabel*> labels_;
// Remember the current state for easy error checking. (We prefer to be
// strict as this class will be exposed at the API.)
enum { kBuilding, kBuilt, kError } state_;
DISALLOW_COPY_AND_ASSIGN(FastAccessorAssembler);
};
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_FAST_ACCESSOR_ASSEMBLER_H_
...@@ -106,10 +106,9 @@ ...@@ -106,10 +106,9 @@
'test-accessors.cc', 'test-accessors.cc',
'test-api.cc', 'test-api.cc',
'test-api.h', 'test-api.h',
# TODO(epertoso): re-enable the following test after the API change is 'test-api-accessors.cc',
# checked in.
# 'test-api-accessors.cc',
'test-api-interceptors.cc', 'test-api-interceptors.cc',
'test-api-fast-accessor-builder.cc',
'test-array-list.cc', 'test-array-list.cc',
'test-ast.cc', 'test-ast.cc',
'test-ast-expression-visitor.cc', 'test-ast-expression-visitor.cc',
......
...@@ -550,6 +550,12 @@ static inline void ExpectUndefined(const char* code) { ...@@ -550,6 +550,12 @@ static inline void ExpectUndefined(const char* code) {
} }
static inline void ExpectNull(const char* code) {
v8::Local<v8::Value> result = CompileRun(code);
CHECK(result->IsNull());
}
static inline void CheckDoubleEquals(double expected, double actual) { static inline void CheckDoubleEquals(double expected, double actual) {
const double kEpsilon = 1e-10; const double kEpsilon = 1e-10;
CHECK_LE(expected, actual + kEpsilon); CHECK_LE(expected, actual + kEpsilon);
......
...@@ -5,35 +5,31 @@ ...@@ -5,35 +5,31 @@
#include "test/cctest/cctest.h" #include "test/cctest/cctest.h"
#include "include/v8.h" #include "include/v8.h"
#include "src/compiler/pipeline.h" #include "include/v8-experimental.h"
#include "src/compiler/raw-machine-assembler.h"
namespace i = v8::internal; namespace i = v8::internal;
static void CppAccessor(const v8::FunctionCallbackInfo<v8::Value>& info) { static void CppAccessor42(const v8::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().Set(42); info.GetReturnValue().Set(42);
} }
v8::Local<v8::Value> RawAccessor(v8::Isolate* isolate) { static void CppAccessor41(const v8::FunctionCallbackInfo<v8::Value>& info) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); info.GetReturnValue().Set(41);
i::Zone zone;
i::compiler::RawMachineAssembler raw_machine_assembler(
i_isolate, new (&zone) i::compiler::Graph(&zone),
i::compiler::Linkage::GetJSCallDescriptor(
&zone, false, 1, i::compiler::CallDescriptor::kNoFlags));
raw_machine_assembler.Return(raw_machine_assembler.NumberConstant(41));
i::CompilationInfo info("firstChildRaw", i_isolate, &zone);
i::compiler::Schedule* schedule = raw_machine_assembler.Export();
i::Handle<i::Code> code = i::compiler::Pipeline::GenerateCodeForTesting(
&info, raw_machine_assembler.call_descriptor(),
raw_machine_assembler.graph(), schedule);
return v8::Utils::ToLocal(i::Handle<i::Object>::cast(code));
} }
TEST(JavascriptAccessors) { v8::experimental::FastAccessorBuilder* FastAccessor(v8::Isolate* isolate) {
auto builder = v8::experimental::FastAccessorBuilder::New(isolate);
builder->ReturnValue(builder->IntegerConstant(41));
return builder;
}
TEST(FastAccessors) {
if (i::FLAG_always_opt || i::FLAG_optimize_for_size) return;
v8::Isolate* isolate = CcTest::isolate(); v8::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate); v8::HandleScope scope(isolate);
LocalContext env; LocalContext env;
...@@ -53,14 +49,14 @@ TEST(JavascriptAccessors) { ...@@ -53,14 +49,14 @@ TEST(JavascriptAccessors) {
// cpp accessor as "firstChild": // cpp accessor as "firstChild":
parent->PrototypeTemplate()->SetAccessorProperty( parent->PrototypeTemplate()->SetAccessorProperty(
v8_str("firstChild"), v8_str("firstChild"),
v8::FunctionTemplate::New(isolate, CppAccessor, v8::Local<v8::Value>(), v8::FunctionTemplate::New(isolate, CppAccessor42,
signature)); v8::Local<v8::Value>(), signature));
// JS accessor as "firstChildRaw": // JS accessor as "firstChildRaw":
auto raw_accessor = RawAccessor(isolate);
parent->PrototypeTemplate()->SetAccessorProperty( parent->PrototypeTemplate()->SetAccessorProperty(
v8_str("firstChildRaw"), v8::FunctionTemplate::NewWithFastHandler( v8_str("firstChildRaw"),
isolate, CppAccessor, raw_accessor, v8::FunctionTemplate::NewWithFastHandler(
isolate, CppAccessor41, FastAccessor(isolate),
v8::Local<v8::Value>(), signature)); v8::Local<v8::Value>(), signature));
} }
......
This diff is collapsed.
...@@ -374,6 +374,7 @@ ...@@ -374,6 +374,7 @@
], ],
'sources': [ ### gcmole(all) ### 'sources': [ ### gcmole(all) ###
'../../include/v8-debug.h', '../../include/v8-debug.h',
'../../include/v8-experimental.h',
'../../include/v8-platform.h', '../../include/v8-platform.h',
'../../include/v8-profiler.h', '../../include/v8-profiler.h',
'../../include/v8-testing.h', '../../include/v8-testing.h',
...@@ -389,6 +390,8 @@ ...@@ -389,6 +390,8 @@
'../../src/allocation.h', '../../src/allocation.h',
'../../src/allocation-site-scopes.cc', '../../src/allocation-site-scopes.cc',
'../../src/allocation-site-scopes.h', '../../src/allocation-site-scopes.h',
'../../src/api-experimental.cc',
'../../src/api-experimental.h',
'../../src/api.cc', '../../src/api.cc',
'../../src/api.h', '../../src/api.h',
'../../src/api-natives.cc', '../../src/api-natives.cc',
...@@ -502,6 +505,8 @@ ...@@ -502,6 +505,8 @@
'../../src/compiler/escape-analysis.h', '../../src/compiler/escape-analysis.h',
"../../src/compiler/escape-analysis-reducer.cc", "../../src/compiler/escape-analysis-reducer.cc",
"../../src/compiler/escape-analysis-reducer.h", "../../src/compiler/escape-analysis-reducer.h",
'../../src/compiler/fast-accessor-assembler.cc',
'../../src/compiler/fast-accessor-assembler.h',
'../../src/compiler/frame.cc', '../../src/compiler/frame.cc',
'../../src/compiler/frame.h', '../../src/compiler/frame.h',
'../../src/compiler/frame-elider.cc', '../../src/compiler/frame-elider.cc',
......
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