⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 builtins.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
// Copyright 2006-2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:////     * Redistributions of source code must retain the above copyright//       notice, this list of conditions and the following disclaimer.//     * Redistributions in binary form must reproduce the above//       copyright notice, this list of conditions and the following//       disclaimer in the documentation and/or other materials provided//       with the distribution.//     * Neither the name of Google Inc. nor the names of its//       contributors may be used to endorse or promote products derived//       from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include "v8.h"#include "api.h"#include "bootstrapper.h"#include "builtins.h"#include "ic-inl.h"namespace v8 { namespace internal {// ----------------------------------------------------------------------------// Support macros for defining builtins in C.// ----------------------------------------------------------------------------//// A builtin function is defined by writing:////   BUILTIN(name) {//     ...//   }//   BUILTIN_END//// In the body of the builtin function, the variable 'receiver' is visible.// The arguments can be accessed through:////   BUILTIN_ARG(0): Receiver (also available as 'receiver')//   BUILTIN_ARG(1): First argument//     ...//   BUILTIN_ARG(n): Last argument//// and they evaluate to undefined values if too few arguments were// passed to the builtin function invocation.//// __argc__ is the number of arguments including the receiver.// ----------------------------------------------------------------------------// TODO(1238487): We should consider passing whether or not the// builtin was invoked as a constructor as part of the// arguments. Maybe we also want to pass the called function?#define BUILTIN(name)                                                   \  static Object* Builtin_##name(int __argc__, Object** __argv__) {      \    Handle<Object> receiver(&__argv__[0]);// Use an inline function to avoid evaluating the index (n) more than// once in the BUILTIN_ARG macro.static inline Object* __builtin_arg__(int n, int argc, Object** argv) {  ASSERT(n >= 0);  return (argc > n) ? argv[-n] : Heap::undefined_value();}// NOTE: Argument 0 is the receiver. The first 'real' argument is// argument 1 - BUILTIN_ARG(1).#define BUILTIN_ARG(n) (__builtin_arg__(n, __argc__, __argv__))#define BUILTIN_END                             \  return Heap::undefined_value();               \}// TODO(1238487): Get rid of this function that determines if the// builtin is called as a constructor. This may be a somewhat slow// operation due to the stack frame iteration.static inline bool CalledAsConstructor() {  StackFrameIterator it;  ASSERT(it.frame()->is_exit());  it.Advance();  StackFrame* frame = it.frame();  return frame->is_internal() &&      InternalFrame::cast(frame)->is_construct_trampoline();}// ----------------------------------------------------------------------------int Builtins::construct_call_pc_offset_ = 0;int Builtins::arguments_adaptor_call_pc_offset_ = 0;// Check if the builtin was called in a 'new' call.bool Builtins::IsConstructCall(Address pc) {  ASSERT(construct_call_pc_offset_ > 0);  int offset = pc - builtin(JSConstructCall)->address();  return offset == construct_call_pc_offset_;}bool Builtins::IsArgumentsAdaptorCall(Address pc) {  ASSERT(arguments_adaptor_call_pc_offset_ > 0);  int offset = pc - builtin(ArgumentsAdaptorTrampoline)->address();  return offset == arguments_adaptor_call_pc_offset_;}Handle<Code> Builtins::GetCode(JavaScript id, bool* resolved) {  Code* code = Builtins::builtin(Builtins::Illegal);  *resolved = false;  if (Top::security_context() != NULL) {    Object* object = Top::security_context_builtins()->javascript_builtin(id);    if (object->IsJSFunction()) {      Handle<JSFunction> function(JSFunction::cast(object));      // Make sure the number of parameters match the formal parameter count.      ASSERT(function->shared()->formal_parameter_count() ==             Builtins::GetArgumentsCount(id));      if (function->is_compiled() || CompileLazy(function, CLEAR_EXCEPTION)) {        code = function->code();        *resolved = true;      }    }  }  return Handle<Code>(code);}BUILTIN(Illegal) {  UNREACHABLE();}BUILTIN_ENDBUILTIN(EmptyFunction) {}BUILTIN_ENDBUILTIN(ArrayCode) {  JSArray* array;  if (CalledAsConstructor()) {    array = JSArray::cast(*receiver);  } else {    // Allocate the JS Array    JSFunction* constructor =        Top::context()->global_context()->array_function();    Object* obj = Heap::AllocateJSObject(constructor);    if (obj->IsFailure()) return obj;    array = JSArray::cast(obj);  }  // 'array' now contains the JSArray we should initialize.  // Optimize the case where there is one argument and the argument is a  // small smi.  if (__argc__ == 2) {    Object* obj = BUILTIN_ARG(1);    if (obj->IsSmi()) {      int len = Smi::cast(obj)->value();      if (len >= 0 && len < JSObject::kMaxFastElementsLength) {        Object* obj = Heap::AllocateFixedArrayWithHoles(len);        if (obj->IsFailure()) return obj;        array->SetContent(FixedArray::cast(obj));        return array;      }    }    // Take the argument as the length.    obj = array->Initialize(0);    if (obj->IsFailure()) return obj;    if (__argc__ == 2) return array->SetElementsLength(BUILTIN_ARG(1));  }  // Optimize the case where there are no parameters passed.  if (__argc__ == 1) return array->Initialize(4);  // Take the arguments as elements.  int number_of_elements = __argc__ - 1;  Smi* len = Smi::FromInt(number_of_elements);  Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());  if (obj->IsFailure()) return obj;  FixedArray* elms = FixedArray::cast(obj);  FixedArray::WriteBarrierMode mode = elms->GetWriteBarrierMode();  // Fill in the content  for (int index = 0; index < number_of_elements; index++) {    elms->set(index, BUILTIN_ARG(index+1), mode);  }  // Set length and elements on the array.  array->set_elements(FixedArray::cast(obj));  array->set_length(len);  return array;}BUILTIN_ENDBUILTIN(ArrayPush) {  JSArray* array = JSArray::cast(*receiver);  ASSERT(array->HasFastElements());  // Make sure we have space for the elements.  int len = Smi::cast(array->length())->value();  // Set new length.  int new_length = len + __argc__ - 1;  FixedArray* elms = FixedArray::cast(array->elements());  if (new_length <= elms->length()) {    // Backing storage has extra space for the provided values.    for (int index = 0; index < __argc__ - 1; index++) {      elms->set(index + len, BUILTIN_ARG(index+1));    }  } else {    // New backing storage is needed.    int capacity = new_length + (new_length >> 1) + 16;    Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);    if (obj->IsFailure()) return obj;    FixedArray* new_elms = FixedArray::cast(obj);    FixedArray::WriteBarrierMode mode = new_elms->GetWriteBarrierMode();    // Fill out the new array with old elements.    for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);    // Add the provided values.    for (int index = 0; index < __argc__ - 1; index++) {      new_elms->set(index + len, BUILTIN_ARG(index+1), mode);    }    // Set the new backing storage.    array->set_elements(new_elms);  }  // Set the length.  array->set_length(Smi::FromInt(new_length));  return array->length();}BUILTIN_ENDBUILTIN(ArrayPop) {  JSArray* array = JSArray::cast(*receiver);  ASSERT(array->HasFastElements());  Object* undefined = Heap::undefined_value();  int len = Smi::cast(array->length())->value();  if (len == 0) return undefined;  // Get top element  FixedArray* elms = FixedArray::cast(array->elements());  Object* top = elms->get(len - 1);  // Set the length.  array->set_length(Smi::FromInt(len - 1));  if (!top->IsTheHole()) {    // Delete the top element.    elms->set_the_hole(len - 1);    return top;  }  // Remember to check the prototype chain.  JSFunction* array_function =      Top::context()->global_context()->array_function();  JSObject* prototype = JSObject::cast(array_function->prototype());  top = prototype->GetElement(len - 1);  return top;}BUILTIN_END// -----------------------------------------------------------------------------//// Returns the holder JSObject if the function can legally be called// with this receiver.  Returns Heap::null_value() if the call is// illegal.  Any arguments that don't fit the expected type is// overwritten with undefined.  Arguments that do fit the expected// type is overwritten with the object in the prototype chain that// actually has that type.static inline Object* TypeCheck(int argc,                                Object** argv,                                FunctionTemplateInfo* info) {  Object* recv = argv[0];  Object* sig_obj = info->signature();  if (sig_obj->IsUndefined()) return recv;  SignatureInfo* sig = SignatureInfo::cast(sig_obj);  // If necessary, check the receiver  Object* recv_type = sig->receiver();  Object* holder = recv;  if (!recv_type->IsUndefined()) {    for (; holder != Heap::null_value(); holder = holder->GetPrototype()) {      if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {        break;      }    }    if (holder == Heap::null_value()) return holder;  }  Object* args_obj = sig->args();  // If there is no argument signature we're done  if (args_obj->IsUndefined()) return holder;  FixedArray* args = FixedArray::cast(args_obj);  int length = args->length();  if (argc <= length) length = argc - 1;  for (int i = 0; i < length; i++) {    Object* argtype = args->get(i);    if (argtype->IsUndefined()) continue;    Object** arg = &argv[-1 - i];    Object* current = *arg;    for (; current != Heap::null_value(); current = current->GetPrototype()) {      if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) {        *arg = current;        break;      }    }    if (current == Heap::null_value()) *arg = Heap::undefined_value();  }  return holder;}BUILTIN(HandleApiCall) {  HandleScope scope;  bool is_construct = CalledAsConstructor();  // TODO(1238487): This is not nice. We need to get rid of this  // kludgy behavior and start handling API calls in a more direct  // way - maybe compile specialized stubs lazily?.  Handle<JSFunction> function =      Handle<JSFunction>(JSFunction::cast(Builtins::builtin_passed_function));  if (is_construct) {    Handle<FunctionTemplateInfo> desc =        Handle<FunctionTemplateInfo>(            FunctionTemplateInfo::cast(function->shared()->function_data()));    bool pending_exception = false;    Factory::ConfigureInstance(desc, Handle<JSObject>::cast(receiver),                               &pending_exception);    ASSERT(Top::has_pending_exception() == pending_exception);    if (pending_exception) return Failure::Exception();  }  FunctionTemplateInfo* fun_data =      FunctionTemplateInfo::cast(function->shared()->function_data());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -