Ejemplo n.º 1
0
function main()
{
    global $scriptPath, $output_file, $extension_src_path;
    global $extension_lib_path, $extensions;
    $ext_func_info = array();
    $ext_class_info = array();
    $mangleMap = array();
    parseIDLForFunctions($ext_func_info, $mangleMap, $scriptPath . '/../../idl/');
    parseIDLForMethods($ext_class_info, $mangleMap, $scriptPath . '/../../idl/');
    $sepExtDirs = getSepExtDirs($extension_src_path, $extensions);
    $sepExtHeaders = getSepExtHeaders($extension_src_path, $extensions);
    foreach ($sepExtDirs as $dir) {
        parseIDLForFunctions($ext_func_info, $mangleMap, $dir);
        parseIDLForMethods($ext_class_info, $mangleMap, $dir);
    }
    try {
        $outfile_tempnam = tempnam('/tmp', 'ext_hhvm.cpp.tmp');
        $outfile = fopen($outfile_tempnam, 'w');
        emit_include($outfile, "runtime/ext_hhvm/ext_hhvm.h");
        emit_include($outfile, "runtime/ext/ext.h");
        fwrite($outfile, "#include \"ext_hhvm_infotabs.h\"\n");
        fwrite($outfile, "namespace HPHP {\n" . "  struct TypedValue;\n" . "  namespace VM { struct ActRec; struct Class; }\n" . "}\n\n");
        fwrite($outfile, "namespace HPHP {\n\n");
        // First declare all the stubs we need to be able to register.
        foreach ($ext_func_info as $obj) {
            fwrite($outfile, "TypedValue* fg_" . $obj->name . "(VM::ActRec *ar);\n");
        }
        foreach ($ext_class_info as $cname => $method_info) {
            fwrite($outfile, "VM::Instance* new_" . $cname . "_Instance(" . "VM::Class*);\n");
            foreach ($method_info as $obj) {
                fwrite($outfile, "TypedValue* tg_" . getUniqueFuncName($obj) . "(VM::ActRec *ar);\n");
            }
        }
        fwrite($outfile, "\n");
        fwrite($outfile, "const long long hhbc_ext_funcs_count = " . count($ext_func_info) . ";\n");
        fwrite($outfile, "const HhbcExtFuncInfo hhbc_ext_funcs[] = {\n  ");
        $firstParam = true;
        foreach ($ext_func_info as $obj) {
            if (!$firstParam) {
                fwrite($outfile, ",\n  ");
            }
            $firstParam = false;
            fwrite($outfile, '{ "' . $obj->name . '", fg_' . $obj->name);
            fwrite($outfile, ', (void *)&fh_' . $obj->name . ' }');
        }
        fwrite($outfile, "\n};\n\n");
        foreach ($ext_class_info as $cname => $method_info) {
            fwrite($outfile, "static const long long hhbc_ext_method_count_" . $cname . " = " . count($method_info) . ";\n");
            fwrite($outfile, "static const HhbcExtMethodInfo hhbc_ext_methods_" . $cname . "[] = {\n  ");
            $firstParam = true;
            foreach ($method_info as $obj) {
                if (!$firstParam) {
                    fwrite($outfile, ",\n  ");
                }
                $firstParam = false;
                fwrite($outfile, '{ "' . $obj->name . '", tg_' . getUniqueFuncName($obj) . ' }');
            }
            fwrite($outfile, "\n};\n\n");
        }
        fwrite($outfile, "const long long hhbc_ext_class_count = " . count($ext_class_info) . ";\n");
        fwrite($outfile, "const HhbcExtClassInfo hhbc_ext_classes[] = {\n  ");
        $firstParam = true;
        foreach ($ext_class_info as $cname => $method_info) {
            if (!$firstParam) {
                fwrite($outfile, ",\n  ");
            }
            $firstParam = false;
            fwrite($outfile, '{ "' . $cname . '", new_' . $cname . '_Instance' . ', sizeof(c_' . $cname . ')' . ', hhbc_ext_method_count_' . $cname . ', hhbc_ext_methods_' . $cname . ' }');
        }
        fwrite($outfile, "\n};\n\n");
        fwrite($outfile, "\n} // !HPHP\n\n");
        fclose($outfile);
        $outfile = null;
        `mv -f {$outfile_tempnam} {$output_file}`;
    } catch (Exception $e) {
        if ($outfile) {
            fclose($outfile);
        }
        if ($outfile_tempnam) {
            `rm -rf {$outfile_tempnam}`;
        }
    }
}
Ejemplo n.º 2
0
function phase2()
{
    global $scriptPath, $output_file, $extension_src_path;
    global $extension_lib_path, $extensions;
    $ext_func_info = array();
    $ext_class_info = array();
    $mangleMap = generateMangleMap();
    parseIDLForFunctions($ext_func_info, $mangleMap, $scriptPath . '/../../idl/', 0);
    parseIDLForMethods($ext_class_info, $mangleMap, $scriptPath . '/../../idl/');
    $sepExtDirs = getSepExtDirs($extension_src_path, $extensions);
    $sepExtHeaders = getSepExtHeaders($extension_src_path, $extensions);
    foreach ($sepExtDirs as $dir) {
        parseIDLForFunctions($ext_func_info, $mangleMap, $dir, 0);
        parseIDLForMethods($ext_class_info, $mangleMap, $dir);
    }
    $ext_hhvm_cpp_tempnam = null;
    $ext_hhvm_cpp = null;
    try {
        $ext_hhvm_cpp_tempnam = tempnam('/tmp', 'ext_hhvm.cpp.tmp');
        $ext_hhvm_cpp = fopen($ext_hhvm_cpp_tempnam, 'w');
        emit_all_includes($ext_hhvm_cpp, $sepExtHeaders);
        fwrite($ext_hhvm_cpp, "namespace HPHP {\n\n");
        // Generate code for extension functions
        foreach ($ext_func_info as $obj) {
            if (!$obj->mangledName) {
                continue;
            }
            // Emit the fh_ function declaration
            $indent = '';
            emitRemappedFuncDecl($obj, $ext_hhvm_cpp, $indent, 'fh_', $mangleMap);
            // Emit the fg1_ function if needed
            if ($obj->numTypeChecks > 0) {
                fwrite($ext_hhvm_cpp, "TypedValue * fg1_" . $obj->name . "(TypedValue* rv, HPHP::VM::ActRec* ar, long long count) " . "__attribute__((noinline,cold));\n");
                fwrite($ext_hhvm_cpp, "TypedValue * fg1_" . $obj->name . "(TypedValue* rv, HPHP::VM::ActRec* ar, long long count) {\n");
                $indent = '  ';
                emitSlowPathHelper($obj, $ext_hhvm_cpp, $indent, 'fh_');
                fwrite($ext_hhvm_cpp, "}\n\n");
            }
            // Start emitting the fg_ function
            fwrite($ext_hhvm_cpp, "TypedValue* fg_" . $obj->name . "(HPHP::VM::ActRec *ar) {\n");
            $indent = '  ';
            $indent .= '  ';
            fwrite($ext_hhvm_cpp, $indent . "TypedValue rv;\n");
            fwrite($ext_hhvm_cpp, $indent . "long long count = ar->numArgs();\n");
            fwrite($ext_hhvm_cpp, $indent . "TypedValue* args UNUSED = ((TypedValue*)ar) - 1;\n");
            $firstParam = true;
            $needElseClause = false;
            if ($obj->isVarargs) {
                if ($obj->minNumParams > 0) {
                    fwrite($ext_hhvm_cpp, $indent . 'if (count >= ' . $obj->minNumParams . 'LL) {' . "\n");
                    $indent .= '  ';
                    $needElseClause = true;
                }
            } else {
                if ($obj->minNumParams == $obj->maxNumParams) {
                    fwrite($ext_hhvm_cpp, $indent . 'if (count == ' . $obj->minNumParams . 'LL) {' . "\n");
                } else {
                    if ($obj->minNumParams == 0) {
                        fwrite($ext_hhvm_cpp, $indent . 'if (count <= ' . $obj->maxNumParams . 'LL) {' . "\n");
                    } else {
                        fwrite($ext_hhvm_cpp, $indent . 'if (count >= ' . $obj->minNumParams . 'LL && count <= ' . $obj->maxNumParams . 'LL) {' . "\n");
                    }
                }
                $indent .= '  ';
                $needElseClause = true;
            }
            if ($obj->numTypeChecks > 0) {
                fwrite($ext_hhvm_cpp, $indent . 'if (');
                emitTypeCheckCondition($obj, $ext_hhvm_cpp);
                fwrite($ext_hhvm_cpp, ") {\n");
                $indent .= '  ';
            }
            emitExtCall($obj, $ext_hhvm_cpp, $indent, 'fh_');
            if ($obj->numTypeChecks > 0) {
                $indent = substr($indent, 2);
                fwrite($ext_hhvm_cpp, $indent . "} else {\n");
                $indent .= '  ';
                fwrite($ext_hhvm_cpp, $indent . "fg1_" . $obj->name . "(&rv, ar, count);\n");
                fwrite($ext_hhvm_cpp, copyAndReturnRV($indent, $obj));
                $indent = substr($indent, 2);
                fwrite($ext_hhvm_cpp, $indent . "}\n");
            }
            if ($needElseClause) {
                $indent = substr($indent, 2);
                fwrite($ext_hhvm_cpp, $indent . '} else {' . "\n");
                $indent .= '  ';
                if ($obj->isVarargs) {
                    fwrite($ext_hhvm_cpp, $indent . 'throw_missing_arguments_nr("' . $obj->name . '", count+1, 1);' . "\n");
                } else {
                    if ($obj->minNumParams == 0) {
                        fwrite($ext_hhvm_cpp, $indent . 'throw_toomany_arguments_nr("' . $obj->name . '", ' . $obj->maxNumParams . ', 1);' . "\n");
                    } else {
                        fwrite($ext_hhvm_cpp, $indent . 'throw_wrong_arguments_nr("' . $obj->name . '", count, ' . $obj->minNumParams . ', ' . $obj->maxNumParams . ', 1);' . "\n");
                    }
                }
                $indent = substr($indent, 2);
                fwrite($ext_hhvm_cpp, $indent . '}' . "\n");
                fwrite($ext_hhvm_cpp, $indent . 'rv.m_data.num = 0LL;' . "\n");
                fwrite($ext_hhvm_cpp, $indent . 'rv._count = 0;' . "\n");
                fwrite($ext_hhvm_cpp, $indent . 'rv.m_type = KindOfNull;' . "\n");
                fwrite($ext_hhvm_cpp, copyAndReturnRV($indent, $obj));
            }
            $indent = substr($indent, 2);
            fwrite($ext_hhvm_cpp, $indent . "return &ar->m_r;\n");
            fwrite($ext_hhvm_cpp, "}\n\n\n\n");
        }
        // Extension classes; member functions and the actual instance
        // object.
        foreach ($ext_class_info as $cname => $method_info) {
            foreach ($method_info as $obj) {
                if (!$obj->mangledName) {
                    continue;
                }
                // Emit the instance definition only in in the file that
                // contains the classes' constructor function.  This is just to
                // avoid multiple definition issues when an extension class is
                // spread among a few cpp files.
                if ($obj->name == "__construct") {
                    emit_ctor_helper($ext_hhvm_cpp, $cname);
                }
                $indent = '';
                // Emit the th_ function declaration
                emitRemappedFuncDecl($obj, $ext_hhvm_cpp, $indent, 'th_', $mangleMap);
                // Emit the tg1_ function if needed
                if ($obj->numTypeChecks > 0) {
                    fwrite($ext_hhvm_cpp, "TypedValue* tg1_" . getUniqueFuncName($obj) . "(TypedValue* rv, HPHP::VM::ActRec* ar, long long count" . (!$obj->isStatic ? ", ObjectData* this_" : "") . ") __attribute__((noinline,cold));\n");
                    fwrite($ext_hhvm_cpp, "TypedValue* tg1_" . getUniqueFuncName($obj) . "(TypedValue* rv, HPHP::VM::ActRec* ar, long long count" . (!$obj->isStatic ? ", ObjectData* this_" : "") . ") {\n");
                    $indent = '  ';
                    emitSlowPathHelper($obj, $ext_hhvm_cpp, $indent, 'th_');
                    fwrite($ext_hhvm_cpp, "}\n\n");
                    $indent = '';
                }
                // Start emitting the tg_ function
                fwrite($ext_hhvm_cpp, "TypedValue* tg_" . getUniqueFuncName($obj) . "(HPHP::VM::ActRec *ar) {\n");
                $indent = '  ';
                $indent .= '  ';
                fwrite($ext_hhvm_cpp, $indent . "TypedValue rv;\n");
                fwrite($ext_hhvm_cpp, $indent . "long long count = ar->numArgs();\n");
                fwrite($ext_hhvm_cpp, $indent . "TypedValue* args UNUSED " . "= ((TypedValue*)ar) - 1;\n");
                if (!$obj->isStatic) {
                    fwrite($ext_hhvm_cpp, $indent . "ObjectData* this_ = (ar->hasThis() ? " . "ar->getThis() : NULL);\n");
                }
                $firstParam = true;
                $needElseClause = false;
                $needsNullReturn = false;
                if (!$obj->isStatic) {
                    fwrite($ext_hhvm_cpp, $indent . "if (this_) {\n");
                    $indent .= '  ';
                    $needsNullReturn = true;
                }
                if ($obj->isVarargs) {
                    if ($obj->minNumParams > 0) {
                        fwrite($ext_hhvm_cpp, $indent . 'if (count >= ' . $obj->minNumParams . 'LL) {' . "\n");
                        $indent .= '  ';
                        $needElseClause = true;
                        $needsNullReturn = true;
                    }
                } else {
                    if ($obj->minNumParams == $obj->maxNumParams) {
                        fwrite($ext_hhvm_cpp, $indent . 'if (count == ' . $obj->minNumParams . 'LL) {' . "\n");
                    } else {
                        if ($obj->minNumParams == 0) {
                            fwrite($ext_hhvm_cpp, $indent . 'if (count <= ' . $obj->maxNumParams . 'LL) {' . "\n");
                        } else {
                            fwrite($ext_hhvm_cpp, $indent . 'if (count >= ' . $obj->minNumParams . 'LL && count <= ' . $obj->maxNumParams . 'LL) {' . "\n");
                        }
                    }
                    $indent .= '  ';
                    $needElseClause = true;
                    $needsNullReturn = true;
                }
                if ($obj->numTypeChecks > 0) {
                    fwrite($ext_hhvm_cpp, $indent . 'if (');
                    emitTypeCheckCondition($obj, $ext_hhvm_cpp);
                    fwrite($ext_hhvm_cpp, ") {\n");
                    $indent .= '  ';
                }
                emitExtCall($obj, $ext_hhvm_cpp, $indent, 'th_');
                if ($obj->numTypeChecks > 0) {
                    $indent = substr($indent, 2);
                    fwrite($ext_hhvm_cpp, $indent . "} else {\n");
                    $indent .= '  ';
                    fwrite($ext_hhvm_cpp, $indent . "tg1_" . getUniqueFuncName($obj) . "(&rv, ar, count " . (!$obj->isStatic ? ", this_" : "") . ");\n");
                    fwrite($ext_hhvm_cpp, copyAndReturnRV($indent, $obj));
                    $indent = substr($indent, 2);
                    fwrite($ext_hhvm_cpp, $indent . "}\n");
                }
                if ($needElseClause) {
                    $indent = substr($indent, 2);
                    fwrite($ext_hhvm_cpp, $indent . '} else {' . "\n");
                    $indent .= '  ';
                    if ($obj->isVarargs) {
                        fwrite($ext_hhvm_cpp, $indent . 'throw_missing_arguments_nr("' . $obj->className . '::' . $obj->name . '", count+1, 1);' . "\n");
                    } else {
                        if ($obj->minNumParams == 0) {
                            fwrite($ext_hhvm_cpp, $indent . 'throw_toomany_arguments_nr("' . $obj->className . '::' . $obj->name . '", ' . $obj->maxNumParams . ', 1);' . "\n");
                        } else {
                            fwrite($ext_hhvm_cpp, $indent . 'throw_wrong_arguments_nr("' . $obj->className . '::' . $obj->name . '", count, ' . $obj->minNumParams . ', ' . $obj->maxNumParams . ', 1);' . "\n");
                        }
                    }
                    $indent = substr($indent, 2);
                    fwrite($ext_hhvm_cpp, $indent . '}' . "\n");
                }
                if (!$obj->isStatic) {
                    $indent = substr($indent, 2);
                    fwrite($ext_hhvm_cpp, $indent . "} else {\n");
                    $indent .= '  ';
                    fwrite($ext_hhvm_cpp, $indent . 'throw_instance_method_fatal("' . $obj->className . '::' . $obj->name . '");' . "\n");
                    $indent = substr($indent, 2);
                    fwrite($ext_hhvm_cpp, $indent . "}\n");
                }
                if ($needsNullReturn) {
                    fwrite($ext_hhvm_cpp, $indent . 'rv.m_data.num = 0LL;' . "\n");
                    fwrite($ext_hhvm_cpp, $indent . 'rv._count = 0;' . "\n");
                    fwrite($ext_hhvm_cpp, $indent . 'rv.m_type = KindOfNull;' . "\n");
                    fwrite($ext_hhvm_cpp, copyAndReturnRV($indent, $obj));
                }
                $indent = substr($indent, 2);
                fwrite($ext_hhvm_cpp, $indent . "return &ar->m_r;\n");
                fwrite($ext_hhvm_cpp, "}\n\n");
            }
        }
        fwrite($ext_hhvm_cpp, "\n} // !HPHP\n\n");
        fclose($ext_hhvm_cpp);
        $ext_hhvm_cpp = null;
        `mv -f {$ext_hhvm_cpp_tempnam} {$output_file}`;
    } catch (Exception $e) {
        if ($ext_hhvm_cpp) {
            fclose($ext_hhvm_cpp);
        }
        if ($ext_hhvm_cpp_tempnam) {
            `rm -rf {$ext_hhvm_cpp_tempnam}`;
        }
    }
}