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

📄 runtime.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
📖 第 1 页 / 共 5 页
字号:
// 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 <stdlib.h>#include "v8.h"#include "accessors.h"#include "api.h"#include "arguments.h"#include "compiler.h"#include "cpu.h"#include "dateparser.h"#include "debug.h"#include "execution.h"#include "jsregexp.h"#include "platform.h"#include "runtime.h"#include "scopeinfo.h"#include "v8threads.h"namespace v8 { namespace internal {#define RUNTIME_ASSERT(value) do {                                   \  if (!(value)) return IllegalOperation();                           \} while (false)// Cast the given object to a value of the specified type and store// it in a variable with the given name.  If the object is not of the// expected type call IllegalOperation and return.#define CONVERT_CHECKED(Type, name, obj)                             \  RUNTIME_ASSERT(obj->Is##Type());                                   \  Type* name = Type::cast(obj);#define CONVERT_ARG_CHECKED(Type, name, index)                       \  RUNTIME_ASSERT(args[index]->Is##Type());                           \  Handle<Type> name = args.at<Type>(index);// Cast the given object to a boolean and store it in a variable with// the given name.  If the object is not a boolean call IllegalOperation// and return.#define CONVERT_BOOLEAN_CHECKED(name, obj)                            \  RUNTIME_ASSERT(obj->IsBoolean());                                   \  bool name = (obj)->IsTrue();// Cast the given object to a double and store it in a variable with// the given name.  If the object is not a number (as opposed to// the number not-a-number) call IllegalOperation and return.#define CONVERT_DOUBLE_CHECKED(name, obj)                            \  RUNTIME_ASSERT(obj->IsNumber());                                   \  double name = (obj)->Number();// Call the specified converter on the object *comand store the result in// a variable of the specified type with the given name.  If the// object is not a Number call IllegalOperation and return.#define CONVERT_NUMBER_CHECKED(type, name, Type, obj)                \  RUNTIME_ASSERT(obj->IsNumber());                                   \  type name = NumberTo##Type(obj);// Non-reentrant string buffer for efficient general use in this file.static StaticResource<StringInputBuffer> string_input_buffer;static Object* IllegalOperation() {  return Top::Throw(Heap::illegal_access_symbol());}static Object* Runtime_CloneObjectLiteralBoilerplate(Arguments args) {  CONVERT_CHECKED(JSObject, boilerplate, args[0]);  return boilerplate->Copy();}static Handle<Map> ComputeObjectLiteralMap(    Handle<Context> context,    Handle<FixedArray> constant_properties,    bool &is_result_from_cache) {  if (FLAG_canonicalize_object_literal_maps) {    // First find prefix of consecutive symbol keys.    int number_of_properties = constant_properties->length()/2;    int number_of_symbol_keys = 0;    while ((number_of_symbol_keys < number_of_properties) &&           (constant_properties->get(number_of_symbol_keys*2)->IsSymbol())) {      number_of_symbol_keys++;    }    // Based on the number of prefix symbols key we decide whether    // to use the map cache in the global context.    const int kMaxKeys = 10;    if ((number_of_symbol_keys == number_of_properties)        && (number_of_symbol_keys < kMaxKeys)) {      // Create the fixed array with the key.      Handle<FixedArray> keys = Factory::NewFixedArray(number_of_symbol_keys);      for (int i = 0; i < number_of_symbol_keys; i++) {        keys->set(i, constant_properties->get(i*2));      }      is_result_from_cache = true;      return Factory::ObjectLiteralMapFromCache(context, keys);    }  }  is_result_from_cache = false;  return Handle<Map>(context->object_function()->initial_map());}static Object* Runtime_CreateObjectLiteralBoilerplate(Arguments args) {  HandleScope scope;  ASSERT(args.length() == 3);  // Copy the arguments.  Handle<FixedArray> literals = args.at<FixedArray>(0);  int literals_index = Smi::cast(args[1])->value();  Handle<FixedArray> constant_properties = args.at<FixedArray>(2);  Handle<Context> context =      Handle<Context>(JSFunction::GlobalContextFromLiterals(*literals));  bool is_result_from_cache;  Handle<Map> map = ComputeObjectLiteralMap(context,                                            constant_properties,                                            is_result_from_cache);  // Get the object function from the literals array.  This is the  // object function from the context in which the function was  // created.  We do not use the object function from the current  // global context because this might be the object function from  // another context which we should not have access to.  Handle<JSObject> boilerplate = Factory::NewJSObjectFromMap(map);  {  // Add the constant propeties to the boilerplate.    int length = constant_properties->length();    OptimizedObjectForAddingMultipleProperties opt(boilerplate,                                                   !is_result_from_cache);    for (int index = 0; index < length; index +=2) {      Handle<Object> key(constant_properties->get(index+0));      Handle<Object> value(constant_properties->get(index+1));      uint32_t element_index = 0;      if (key->IsSymbol()) {        // If key is a symbol it is not an array element.        Handle<String> name(String::cast(*key));        ASSERT(!name->AsArrayIndex(&element_index));        SetProperty(boilerplate, name, value, NONE);      } else if (Array::IndexFromObject(*key, &element_index)) {        // Array index (uint32).        SetElement(boilerplate, element_index, value);      } else {        // Non-uint32 number.        ASSERT(key->IsNumber());        double num = key->Number();        char arr[100];        Vector<char> buffer(arr, ARRAY_SIZE(arr));        const char* str = DoubleToCString(num, buffer);        Handle<String> name = Factory::NewStringFromAscii(CStrVector(str));        SetProperty(boilerplate, name, value, NONE);      }    }  }  // Update the functions literal and return the boilerplate.  literals->set(literals_index, *boilerplate);  return *boilerplate;}static Object* Runtime_CreateArrayLiteral(Arguments args) {  // Takes a FixedArray of elements containing the literal elements of  // the array literal and produces JSArray with those elements.  // Additionally takes the literals array of the surrounding function  // which contains the Array function to use for creating the array  // literal.  ASSERT(args.length() == 2);  CONVERT_CHECKED(FixedArray, elements, args[0]);  CONVERT_CHECKED(FixedArray, literals, args[1]);  JSFunction* constructor =      JSFunction::GlobalContextFromLiterals(literals)->array_function();  // Create the JSArray.  Object* object = Heap::AllocateJSObject(constructor);  if (object->IsFailure()) return object;  // Copy the elements.  Object* content = elements->Copy();  if (content->IsFailure()) return content;  // Set the elements.  JSArray::cast(object)->SetContent(FixedArray::cast(content));  return object;}static Object* Runtime_ClassOf(Arguments args) {  NoHandleAllocation ha;  ASSERT(args.length() == 1);  Object* obj = args[0];  if (!obj->IsJSObject()) return Heap::null_value();  return JSObject::cast(obj)->class_name();}static Object* Runtime_IsInPrototypeChain(Arguments args) {  NoHandleAllocation ha;  ASSERT(args.length() == 2);  // See ECMA-262, section 15.3.5.3, page 88 (steps 5 - 8).  Object* O = args[0];  Object* V = args[1];  while (true) {    Object* prototype = V->GetPrototype();    if (prototype->IsNull()) return Heap::false_value();    if (O == prototype) return Heap::true_value();    V = prototype;  }}static Object* Runtime_IsConstructCall(Arguments args) {  NoHandleAllocation ha;  ASSERT(args.length() == 0);  JavaScriptFrameIterator it;  return Heap::ToBoolean(it.frame()->IsConstructor());}static Object* Runtime_RegExpCompile(Arguments args) {  HandleScope scope;  // create a new handle scope  ASSERT(args.length() == 3);  CONVERT_CHECKED(JSRegExp, raw_re, args[0]);  Handle<JSRegExp> re(raw_re);  CONVERT_CHECKED(String, raw_pattern, args[1]);  Handle<String> pattern(raw_pattern);  CONVERT_CHECKED(String, raw_flags, args[2]);  Handle<String> flags(raw_flags);  return *RegExpImpl::JsreCompile(re, pattern, flags);}static Object* Runtime_CreateApiFunction(Arguments args) {  HandleScope scope;  ASSERT(args.length() == 1);  CONVERT_CHECKED(FunctionTemplateInfo, raw_data, args[0]);  Handle<FunctionTemplateInfo> data(raw_data);  return *Factory::CreateApiFunction(data);}static Object* Runtime_IsTemplate(Arguments args) {  ASSERT(args.length() == 1);  Object* arg = args[0];  bool result = arg->IsObjectTemplateInfo() || arg->IsFunctionTemplateInfo();  return Heap::ToBoolean(result);}static Object* Runtime_GetTemplateField(Arguments args) {  ASSERT(args.length() == 2);  CONVERT_CHECKED(HeapObject, templ, args[0]);  RUNTIME_ASSERT(templ->IsStruct());  CONVERT_CHECKED(Smi, field, args[1]);  return HeapObject::GetHeapObjectField(templ, field->value());}static Object* ThrowRedeclarationError(const char* type, Handle<String> name) {  HandleScope scope;  Handle<Object> type_handle = Factory::NewStringFromAscii(CStrVector(type));  Handle<Object> args[2] = { type_handle, name };  Handle<Object> error =      Factory::NewTypeError("redeclaration", HandleVector(args, 2));  return Top::Throw(*error);}static Object* Runtime_DeclareGlobals(Arguments args) {  HandleScope scope;  Handle<GlobalObject> global = Handle<GlobalObject>(Top::context()->global());  CONVERT_ARG_CHECKED(FixedArray, pairs, 0);  Handle<Context> context = args.at<Context>(1);  bool is_eval = Smi::cast(args[2])->value() == 1;  // Compute the property attributes. According to ECMA-262, section  // 13, page 71, the property must be read-only and  // non-deletable. However, neither SpiderMonkey nor KJS creates the  // property as read-only, so we don't either.  PropertyAttributes base = is_eval ? NONE : DONT_DELETE;  // Only optimize the object if we intend to add more than 5 properties.  OptimizedObjectForAddingMultipleProperties ba(global, pairs->length()/2 > 5);  // Traverse the name/value pairs and set the properties.  int length = pairs->length();  for (int i = 0; i < length; i += 2) {    HandleScope scope;    Handle<String> name(String::cast(pairs->get(i)));    Handle<Object> value(pairs->get(i + 1));    // We have to declare a global const property. To capture we only    // assign to it when evaluating the assignment for "const x =    // <expr>" the initial value is the hole.    bool is_const_property = value->IsTheHole();    if (value->IsUndefined() || is_const_property) {      // Lookup the property in the global object, and don't set the      // value of the variable if the property is already there.      LookupResult lookup;      global->Lookup(*name, &lookup);      if (lookup.IsProperty()) {        // Determine if the property is local by comparing the holder        // against the global object. The information will be used to        // avoid throwing re-declaration errors when declaring        // variables or constants that exist in the prototype chain.        bool is_local = (*global == lookup.holder());        // Get the property attributes and determine if the property is        // read-only.        PropertyAttributes attributes = global->GetPropertyAttribute(*name);        bool is_read_only = (attributes & READ_ONLY) != 0;        if (lookup.type() == INTERCEPTOR) {          // If the interceptor says the property is there, we          // just return undefined without overwriting the property.          // Otherwise, we continue to setting the property.          if (attributes != ABSENT) {            // Check if the existing property conflicts with regards to const.            if (is_local && (is_read_only || is_const_property)) {              const char* type = (is_read_only) ? "const" : "var";              return ThrowRedeclarationError(type, name);            };            // The property already exists without conflicting: Go to            // the next declaration.            continue;          }          // Fall-through and introduce the absent property by using          // SetProperty.        } else {          if (is_local && (is_read_only || is_const_property)) {            const char* type = (is_read_only) ? "const" : "var";            return ThrowRedeclarationError(type, name);          }          // The property already exists without conflicting: Go to          // the next declaration.          continue;        }      }    } else {      // Copy the function and update its context. Use it as value.      Handle<JSFunction> boilerplate = Handle<JSFunction>::cast(value);      Handle<JSFunction> function =          Factory::NewFunctionFromBoilerplate(boilerplate, context);      value = function;    }    LookupResult lookup;    global->LocalLookup(*name, &lookup);    PropertyAttributes attributes = is_const_property        ? static_cast<PropertyAttributes>(base | READ_ONLY)        : base;    if (lookup.IsProperty()) {      // There's a local property that we need to overwrite because      // we're either declaring a function or there's an interceptor      // that claims the property is absent.      // Check for conflicting re-declarations. We cannot have      // conflicting types in case of intercepted properties because      // they are absent.      if (lookup.type() != INTERCEPTOR &&          (lookup.IsReadOnly() || is_const_property)) {        const char* type = (lookup.IsReadOnly()) ? "const" : "var";        return ThrowRedeclarationError(type, name);      }      SetProperty(global, name, value, attributes);    } else {      // If a property with this name does not already exist on the

⌨️ 快捷键说明

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