MacroAssembler::MacroAssembler(void* buffer, int size)
: Assembler(buffer, size),
- unresolved_(0),
generating_stub_(false),
allow_stub_calls_(true),
code_object_(Heap::undefined_value()) {
}
-Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id,
- bool* resolved) {
- // Contract with compiled functions is that the function is passed in r1.
- int builtins_offset =
- JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize);
- ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
- ldr(r1, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
- ldr(r1, FieldMemOperand(r1, builtins_offset));
-
- return Builtins::GetCode(id, resolved);
-}
-
-
void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id,
InvokeJSFlags flags) {
- bool resolved;
- Handle<Code> code = ResolveBuiltin(id, &resolved);
-
+ GetBuiltinEntry(r2, id);
if (flags == CALL_JS) {
- Call(code, RelocInfo::CODE_TARGET);
+ Call(r2);
} else {
ASSERT(flags == JUMP_JS);
- Jump(code, RelocInfo::CODE_TARGET);
- }
-
- if (!resolved) {
- const char* name = Builtins::GetName(id);
- int argc = Builtins::GetArgumentsCount(id);
- uint32_t flags =
- Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
- Bootstrapper::FixupFlagsUseCodeObject::encode(false);
- Unresolved entry = { pc_offset() - kInstrSize, flags, name };
- unresolved_.Add(entry);
+ Jump(r2);
}
}
void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
- bool resolved;
- Handle<Code> code = ResolveBuiltin(id, &resolved);
-
- mov(target, Operand(code));
- if (!resolved) {
- const char* name = Builtins::GetName(id);
- int argc = Builtins::GetArgumentsCount(id);
- uint32_t flags =
- Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
- Bootstrapper::FixupFlagsUseCodeObject::encode(true);
- Unresolved entry = { pc_offset() - kInstrSize, flags, name };
- unresolved_.Add(entry);
- }
-
+ // Load the JavaScript builtin function from the builtins object.
+ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ ldr(r1, FieldMemOperand(r1, GlobalObject::kBuiltinsOffset));
+ int builtins_offset =
+ JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize);
+ ldr(r1, FieldMemOperand(r1, builtins_offset));
+ // Load the code entry point from the function into the target register.
+ ldr(target, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
+ ldr(target, FieldMemOperand(target, SharedFunctionInfo::kCodeOffset));
add(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
}
// setup the function in r1.
void GetBuiltinEntry(Register target, Builtins::JavaScript id);
- struct Unresolved {
- int pc;
- uint32_t flags; // see Bootstrapper::FixupFlags decoders/encoders.
- const char* name;
- };
- List<Unresolved>* unresolved() { return &unresolved_; }
-
Handle<Object> CodeObject() { return code_object_; }
Label* done,
InvokeFlag flag);
- // Prepares for a call or jump to a builtin by doing two things:
- // 1. Emits code that fetches the builtin's function object from the context
- // at runtime, and puts it in the register rdi.
- // 2. Fetches the builtin's code object, and returns it in a handle, at
- // compile time, so that later code can emit instructions to jump or call
- // the builtin directly. If the code object has not yet been created, it
- // returns the builtin code object for IllegalFunction, and sets the
- // output parameter "resolved" to false. Code that uses the return value
- // should then add the address and the builtin name to the list of fixups
- // called unresolved_, which is fixed up by the bootstrapper.
- Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
-
// Activation support.
void EnterFrame(StackFrame::Type type);
void LeaveFrame(StackFrame::Type type);
- List<Unresolved> unresolved_;
bool generating_stub_;
bool allow_stub_calls_;
// This handle will be patched with the code object on installation.
}
-// Pending fixups are code positions that refer to builtin code
-// objects that were not available at the time the code was generated.
-// The pending list is processed whenever an environment has been
-// created.
-class PendingFixups : public AllStatic {
- public:
- static void Add(Code* code, MacroAssembler* masm);
- static bool Process(Handle<JSBuiltinsObject> builtins);
-
- static void Iterate(ObjectVisitor* v);
-
- private:
- static List<Object*> code_;
- static List<const char*> name_;
- static List<int> pc_;
- static List<uint32_t> flags_;
-
- static void Clear();
-};
-
-
-List<Object*> PendingFixups::code_(0);
-List<const char*> PendingFixups::name_(0);
-List<int> PendingFixups::pc_(0);
-List<uint32_t> PendingFixups::flags_(0);
-
-
-void PendingFixups::Add(Code* code, MacroAssembler* masm) {
- // Note this code is not only called during bootstrapping.
- List<MacroAssembler::Unresolved>* unresolved = masm->unresolved();
- int n = unresolved->length();
- for (int i = 0; i < n; i++) {
- const char* name = unresolved->at(i).name;
- code_.Add(code);
- name_.Add(name);
- pc_.Add(unresolved->at(i).pc);
- flags_.Add(unresolved->at(i).flags);
- LOG(StringEvent("unresolved", name));
- }
-}
-
-
-bool PendingFixups::Process(Handle<JSBuiltinsObject> builtins) {
- HandleScope scope;
- // NOTE: Extra fixups may be added to the list during the iteration
- // due to lazy compilation of functions during the processing. Do not
- // cache the result of getting the length of the code list.
- for (int i = 0; i < code_.length(); i++) {
- const char* name = name_[i];
- uint32_t flags = flags_[i];
- Handle<String> symbol = Factory::LookupAsciiSymbol(name);
- Object* o = builtins->GetProperty(*symbol);
-#ifdef DEBUG
- if (!o->IsJSFunction()) {
- V8_Fatal(__FILE__, __LINE__, "Cannot resolve call to builtin %s", name);
- }
-#endif
- Handle<SharedFunctionInfo> shared(JSFunction::cast(o)->shared());
- // Make sure the number of parameters match the formal parameter count.
- int argc = Bootstrapper::FixupFlagsArgumentsCount::decode(flags);
- USE(argc);
- ASSERT(shared->formal_parameter_count() == argc);
- // Do lazy compilation if necessary and check for stack overflows.
- if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) {
- Clear();
- return false;
- }
- Code* code = Code::cast(code_[i]);
- Address pc = code->instruction_start() + pc_[i];
- RelocInfo target(pc, RelocInfo::CODE_TARGET, 0);
- bool use_code_object = Bootstrapper::FixupFlagsUseCodeObject::decode(flags);
- if (use_code_object) {
- target.set_target_object(shared->code());
- } else {
- target.set_target_address(shared->code()->instruction_start());
- }
- LOG(StringEvent("resolved", name));
- }
- Clear();
-
- // TODO(1240818): We should probably try to avoid doing this for all
- // the V8 builtin JS files. It should only happen after running
- // runtime.js - just like there shouldn't be any fixups left after
- // that.
- for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
- Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
- Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id));
- JSFunction* function = JSFunction::cast(builtins->GetProperty(*name));
- builtins->set_javascript_builtin(id, function);
- }
-
- return true;
-}
-
-
-void PendingFixups::Clear() {
- code_.Clear();
- name_.Clear();
- pc_.Clear();
- flags_.Clear();
-}
-
-
-void PendingFixups::Iterate(ObjectVisitor* v) {
- if (!code_.is_empty()) {
- v->VisitPointers(&code_[0], &code_[0] + code_.length());
- }
-}
-
-
class Genesis BASE_EMBEDDED {
public:
Genesis(Handle<Object> global_object,
bool InstallExtension(const char* name);
bool InstallExtension(v8::RegisteredExtension* current);
bool InstallSpecialObjects();
+ bool InstallJSBuiltins(Handle<JSBuiltinsObject> builtins);
bool ConfigureApiObject(Handle<JSObject> object,
Handle<ObjectTemplateInfo> object_template);
bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template);
v->Synchronize("NativesCache");
extensions_cache.Iterate(v);
v->Synchronize("Extensions");
- PendingFixups::Iterate(v);
- v->Synchronize("PendingFixups");
-}
-
-
-// While setting up the environment, we collect code positions that
-// need to be patched before we can run any code in the environment.
-void Bootstrapper::AddFixup(Code* code, MacroAssembler* masm) {
- PendingFixups::Add(code, masm);
}
Handle<Object> result =
Execution::Call(fun, receiver, 0, NULL, &has_pending_exception);
if (has_pending_exception) return false;
- return PendingFixups::Process(
- Handle<JSBuiltinsObject>(Top::context()->builtins()));
+ return true;
}
i < Natives::GetBuiltinsCount();
i++) {
if (!CompileBuiltin(i)) return false;
+ // TODO(ager): We really only need to install the JS builtin
+ // functions on the builtins object after compiling and running
+ // runtime.js.
+ if (!InstallJSBuiltins(builtins)) return false;
}
// Setup natives with lazy loading.
}
+bool Genesis::InstallJSBuiltins(Handle<JSBuiltinsObject> builtins) {
+ HandleScope scope;
+ for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) {
+ Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i);
+ Handle<String> name = Factory::LookupAsciiSymbol(Builtins::GetName(id));
+ Handle<JSFunction> function
+ = Handle<JSFunction>(JSFunction::cast(builtins->GetProperty(*name)));
+ builtins->set_javascript_builtin(id, *function);
+ Handle<SharedFunctionInfo> shared
+ = Handle<SharedFunctionInfo>(function->shared());
+ if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false;
+ }
+ return true;
+}
+
+
bool Genesis::ConfigureGlobalObjects(
v8::Handle<v8::ObjectTemplate> global_proxy_template) {
Handle<JSObject> global_proxy(
Handle<JSFunction>* handle);
static void NativesCacheAdd(Vector<const char> name, Handle<JSFunction> fun);
- // Append code that needs fixup at the end of boot strapping.
- static void AddFixup(Code* code, MacroAssembler* masm);
-
// Tells whether bootstrapping is active.
static bool IsActive();
// ----------------------------------------------------------------------------
-Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {
- Code* code = Builtins::builtin(Builtins::Illegal);
- *resolved = false;
-
- if (Top::context() != NULL) {
- Object* object = Top::builtins()->javascript_builtin(id);
- if (object->IsJSFunction()) {
- Handle<SharedFunctionInfo> shared(JSFunction::cast(object)->shared());
- // Make sure the number of parameters match the formal parameter count.
- ASSERT(shared->formal_parameter_count() ==
- Builtins::GetArgumentsCount(id));
- if (EnsureCompiled(shared, CLEAR_EXCEPTION)) {
- code = shared->code();
- *resolved = true;
- }
- }
- }
-
- return Handle<Code>(code);
-}
-
-
BUILTIN(Illegal) {
UNREACHABLE();
return Heap::undefined_value(); // Make compiler happy.
v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
}
}
- // Add any unresolved jumps or calls to the fixup list in the
- // bootstrapper.
- Bootstrapper::AddFixup(Code::cast(code), &masm);
// Log the event and add the code to the builtins array.
LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
Code::cast(code), functions[i].s_name));
void CodeStub::RecordCodeGeneration(Code* code, MacroAssembler* masm) {
code->set_major_key(MajorKey());
- // Add unresolved entries in the code to the fixup list.
- Bootstrapper::AddFixup(code, masm);
-
#ifdef ENABLE_OPROFILE_AGENT
// Register the generated stub with the OPROFILE agent.
OProfileAgent::CreateNativeCodeRegion(GetName(),
Handle<Code> code =
Factory::NewCode(desc, &sinfo, flags, masm->CodeObject());
- // Add unresolved entries in the code to the fixup list.
- Bootstrapper::AddFixup(*code, masm);
-
#ifdef ENABLE_DISASSEMBLER
bool print_code = Bootstrapper::IsActive()
? FLAG_print_builtin_code
MacroAssembler::MacroAssembler(void* buffer, int size)
: Assembler(buffer, size),
- unresolved_(0),
generating_stub_(false),
allow_stub_calls_(true),
code_object_(Heap::undefined_value()) {
void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
- bool resolved;
- Handle<Code> code = ResolveBuiltin(id, &resolved);
-
// Calls are not allowed in some stubs.
ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
// arguments match the expected number of arguments. Fake a
// parameter count to avoid emitting code to do the check.
ParameterCount expected(0);
- InvokeCode(Handle<Code>(code), expected, expected,
- RelocInfo::CODE_TARGET, flag);
-
- const char* name = Builtins::GetName(id);
- int argc = Builtins::GetArgumentsCount(id);
-
- if (!resolved) {
- uint32_t flags =
- Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
- Bootstrapper::FixupFlagsUseCodeObject::encode(false);
- Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name };
- unresolved_.Add(entry);
- }
+ GetBuiltinEntry(edx, id);
+ InvokeCode(Operand(edx), expected, expected, flag);
}
void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
- bool resolved;
- Handle<Code> code = ResolveBuiltin(id, &resolved);
-
- const char* name = Builtins::GetName(id);
- int argc = Builtins::GetArgumentsCount(id);
-
- mov(Operand(target), Immediate(code));
- if (!resolved) {
- uint32_t flags =
- Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
- Bootstrapper::FixupFlagsUseCodeObject::encode(true);
- Unresolved entry = { pc_offset() - sizeof(int32_t), flags, name };
- unresolved_.Add(entry);
- }
- add(Operand(target), Immediate(Code::kHeaderSize - kHeapObjectTag));
-}
-
-
-Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id,
- bool* resolved) {
- // Move the builtin function into the temporary function slot by
- // reading it from the builtins object. NOTE: We should be able to
- // reduce this to two instructions by putting the function table in
- // the global object instead of the "builtins" object and by using a
- // real register for the function.
- mov(edx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
- mov(edx, FieldOperand(edx, GlobalObject::kBuiltinsOffset));
+ // Load the JavaScript builtin function from the builtins object.
+ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ mov(edi, FieldOperand(edi, GlobalObject::kBuiltinsOffset));
int builtins_offset =
JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize);
- mov(edi, FieldOperand(edx, builtins_offset));
-
- return Builtins::GetCode(id, resolved);
+ mov(edi, FieldOperand(edi, builtins_offset));
+ // Load the code entry point from the function into the target register.
+ mov(target, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
+ mov(target, FieldOperand(target, SharedFunctionInfo::kCodeOffset));
+ add(Operand(target), Immediate(Code::kHeaderSize - kHeapObjectTag));
}
void Move(Register target, Handle<Object> value);
- struct Unresolved {
- int pc;
- uint32_t flags; // see Bootstrapper::FixupFlags decoders/encoders.
- const char* name;
- };
- List<Unresolved>* unresolved() { return &unresolved_; }
-
Handle<Object> CodeObject() { return code_object_; }
Label *on_not_flat_ascii_strings);
private:
- List<Unresolved> unresolved_;
bool generating_stub_;
bool allow_stub_calls_;
// This handle will be patched with the code object on installation.
Label* done,
InvokeFlag flag);
- // Prepares for a call or jump to a builtin by doing two things:
- // 1. Emits code that fetches the builtin's function object from the context
- // at runtime, and puts it in the register rdi.
- // 2. Fetches the builtin's code object, and returns it in a handle, at
- // compile time, so that later code can emit instructions to jump or call
- // the builtin directly. If the code object has not yet been created, it
- // returns the builtin code object for IllegalFunction, and sets the
- // output parameter "resolved" to false. Code that uses the return value
- // should then add the address and the builtin name to the list of fixups
- // called unresolved_, which is fixed up by the bootstrapper.
- Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
-
// Activation support.
void EnterFrame(StackFrame::Type type);
void LeaveFrame(StackFrame::Type type);
MacroAssembler::MacroAssembler(void* buffer, int size)
: Assembler(buffer, size),
- unresolved_(0),
generating_stub_(false),
allow_stub_calls_(true),
code_object_(Heap::undefined_value()) {
}
-void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
- bool resolved;
- Handle<Code> code = ResolveBuiltin(id, &resolved);
-
- const char* name = Builtins::GetName(id);
- int argc = Builtins::GetArgumentsCount(id);
+void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
+ // Calls are not allowed in some stubs.
+ ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
- movq(target, code, RelocInfo::EMBEDDED_OBJECT);
- if (!resolved) {
- uint32_t flags =
- Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
- Bootstrapper::FixupFlagsUseCodeObject::encode(true);
- Unresolved entry = { pc_offset() - sizeof(intptr_t), flags, name };
- unresolved_.Add(entry);
- }
- addq(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
+ // Rely on the assertion to check that the number of provided
+ // arguments match the expected number of arguments. Fake a
+ // parameter count to avoid emitting code to do the check.
+ ParameterCount expected(0);
+ GetBuiltinEntry(rdx, id);
+ InvokeCode(rdx, expected, expected, flag);
}
-Handle<Code> MacroAssembler::ResolveBuiltin(Builtins::JavaScript id,
- bool* resolved) {
- // Move the builtin function into the temporary function slot by
- // reading it from the builtins object. NOTE: We should be able to
- // reduce this to two instructions by putting the function table in
- // the global object instead of the "builtins" object and by using a
- // real register for the function.
- movq(rdx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
- movq(rdx, FieldOperand(rdx, GlobalObject::kBuiltinsOffset));
+
+void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
+ // Load the JavaScript builtin function from the builtins object.
+ movq(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ movq(rdi, FieldOperand(rdi, GlobalObject::kBuiltinsOffset));
int builtins_offset =
JSBuiltinsObject::kJSBuiltinsOffset + (id * kPointerSize);
- movq(rdi, FieldOperand(rdx, builtins_offset));
-
- return Builtins::GetCode(id, resolved);
+ movq(rdi, FieldOperand(rdi, builtins_offset));
+ // Load the code entry point from the function into the target register.
+ movq(target, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
+ movq(target, FieldOperand(target, SharedFunctionInfo::kCodeOffset));
+ addq(target, Immediate(Code::kHeaderSize - kHeapObjectTag));
}
#endif // ENABLE_DEBUGGER_SUPPORT
-void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
- bool resolved;
- Handle<Code> code = ResolveBuiltin(id, &resolved);
-
- // Calls are not allowed in some stubs.
- ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
-
- // Rely on the assertion to check that the number of provided
- // arguments match the expected number of arguments. Fake a
- // parameter count to avoid emitting code to do the check.
- ParameterCount expected(0);
- InvokeCode(Handle<Code>(code),
- expected,
- expected,
- RelocInfo::CODE_TARGET,
- flag);
-
- const char* name = Builtins::GetName(id);
- int argc = Builtins::GetArgumentsCount(id);
- // The target address for the jump is stored as an immediate at offset
- // kInvokeCodeAddressOffset.
- if (!resolved) {
- uint32_t flags =
- Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
- Bootstrapper::FixupFlagsUseCodeObject::encode(false);
- Unresolved entry =
- { pc_offset() - kCallTargetAddressOffset, flags, name };
- unresolved_.Add(entry);
- }
-}
-
-
void MacroAssembler::InvokePrologue(const ParameterCount& expected,
const ParameterCount& actual,
Handle<Code> code_constant,
void Ret();
- struct Unresolved {
- int pc;
- uint32_t flags; // see Bootstrapper::FixupFlags decoders/encoders.
- const char* name;
- };
- List<Unresolved>* unresolved() { return &unresolved_; }
-
Handle<Object> CodeObject() { return code_object_; }
bool allow_stub_calls() { return allow_stub_calls_; }
private:
- List<Unresolved> unresolved_;
bool generating_stub_;
bool allow_stub_calls_;
// This handle will be patched with the code object on installation.
Label* done,
InvokeFlag flag);
- // Prepares for a call or jump to a builtin by doing two things:
- // 1. Emits code that fetches the builtin's function object from the context
- // at runtime, and puts it in the register rdi.
- // 2. Fetches the builtin's code object, and returns it in a handle, at
- // compile time, so that later code can emit instructions to jump or call
- // the builtin directly. If the code object has not yet been created, it
- // returns the builtin code object for IllegalFunction, and sets the
- // output parameter "resolved" to false. Code that uses the return value
- // should then add the address and the builtin name to the list of fixups
- // called unresolved_, which is fixed up by the bootstrapper.
- Handle<Code> ResolveBuiltin(Builtins::JavaScript id, bool* resolved);
-
// Activation support.
void EnterFrame(StackFrame::Type type);
void LeaveFrame(StackFrame::Type type);